MatrixAI / Polykey

Polykey Core Library
https://polykey.com
GNU General Public License v3.0
29 stars 4 forks source link

Create IPC locking library `@matrixai/js-file-locks` to introduce RWlocks in IPC #290

Open joshuakarp opened 2 years ago

joshuakarp commented 2 years ago

Specification

We'd like to investigate creating our own locking library, based off our current usage of fd-lock.

Previously we were using both proper-lockfile and fd-lock in a more conglomerated fashion. Now, we are purely using fd-lock for the Status (our refactored agent lockfile https://github.com/MatrixAI/js-polykey/pull/283) and Session usage (implemented here).

Note the distinction between "locking" here. Here, we're referring to "file locking" (as per the fd prefix). For example, for the Status, we lock this status file to assert that an agent process is currently executing. Conversely, we're using async-mutex for intra-process locking (locking some resource from within a process, as opposed to between processes). Remember that we also have an existing read-write locking implementation that utilises async-mutex.

Our own library should support:

OS-specific read-write locks should be the initial priority, and should be seen as a basic extension of functionality from fd-lock (we can use this as a source of inspiration to copy from).

Additional context

Tasks

  1. ...
  2. ...
  3. ...
CMCDragonkai commented 2 years ago

Note that async-mutex is an in-process locking, while file locking is for inter-process locking. We would want to expose rwlocks directly from flock and equivalent in windows for this to work.

CMCDragonkai commented 2 years ago

The src/utils.ts is now src/utils. It's now a directory with src/utils/locks.ts which contains all locking utility functions.

Here is where the RWLock based on async-mutex is. Can be used for other locking utilities that use file locking, or more abstractions are built on top of IPC file locking or in-memory async-mutex (promise-based) locking.

CMCDragonkai commented 2 years ago

As discussed in https://github.com/MatrixAI/js-polykey/pull/283#issuecomment-981248910, there's a problem with Status where it's possible for readStatus to get an "intermediate state" of the status file, such as between truncation and writing. This is not ideal, although a rare situation. Once we have IPC file-based RWlocking, then we can ensure that such reads are not interrupted such writes and no intermediate states are possible. Note that due to the way status works, this may require either 2 files breaking up status.json to 2 files: status.json and status.lock, or if we implement a rw-lock upgrade logic which must work on all platforms natively too.

CMCDragonkai commented 2 years ago

Just experienced the intermittent ErrorStatusParse error that comes from not having a robust IPC. But this is temporary so for now we just have to accept that it sometimes happens.

 FAIL  tests/bin/agent/start.test.ts (71.003 s)
  ● start › start in background

    ErrorStatusParse: JSON parsing failed

      115 |       statusInfo = JSON.parse(statusData);
      116 |     } catch (e) {
    > 117 |       throw new statusErrors.ErrorStatusParse('JSON parsing failed');
          |             ^
      118 |     }
      119 |     if (!statusUtils.statusValidate(statusInfo)) {
      120 |       throw new statusErrors.ErrorStatusParse('StatusInfo validation failed', {

      at Object.readStatus (src/status/Status.ts:117:13)
      at statusInfo (src/status/Status.ts:152:16)
      at poll (src/utils/utils.ts:123:18)
      at Object.waitFor (src/status/Status.ts:150:24)
      at Object.<anonymous> (tests/bin/agent/start.test.ts:142:27)
CMCDragonkai commented 2 years ago

I've developed a read-preferring and write-preferring in-memory RWLock for JS: https://gist.github.com/CMCDragonkai/4de5c1526fc58dac259e321db8cf5331

We may even have a general library for locking that incorporates these features.

CMCDragonkai commented 2 years ago

Good reference for IPC locking on Linux: https://gavv.github.io/articles/file-locks/#bsd-locks-flock

MacOS and Windows might have unique things too.

CMCDragonkai commented 2 years ago

This will be the one https://github.com/MatrixAI/js-file-locks will be imported as @matrixai/file-locks.

CMCDragonkai commented 2 years ago

Updated this to focus on IPC locking, so @matrixai/js-async-locks can be done beforehand and there are many places where in-memory RWLock will be sufficient to solve the MatrixAI/Polykey#294 problem. Which should be addressed in MatrixAI/Polykey#366.