Open joshuakarp opened 3 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.
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.
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.
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)
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.
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.
This will be the one https://github.com/MatrixAI/js-file-locks will be imported as @matrixai/file-locks
.
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.
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
andfd-lock
in a more conglomerated fashion. Now, we are purely usingfd-lock
for theStatus
(our refactored agent lockfile https://github.com/MatrixAI/js-polykey/pull/283) andSession
usage (implemented here).Note the distinction between "locking" here. Here, we're referring to "file locking" (as per the
fd
prefix). For example, for theStatus
, we lock this status file to assert that an agent process is currently executing. Conversely, we're usingasync-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 utilisesasync-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