@david.uhlir/files-scope
v1.1.2
Published
Safe files scope with mutexes for node.js apllications
Downloads
1,352
Readme
Files scope for node.js applications
Basic about
Files scope is util to handle complex work with content of files with mutexes. For example in some cases, you need to read content, process it somehow, and than save it. During this operation, somebody can change content of this file, that's why you should wait until one opration is done, before starting next one. Also all operations done in this scope by provided fs reference, or dependency file api, will be stored in memfs, until scope will be finished. This is where files scope is helpfull, you can open scope, with defining what will be sources, you will need inside. All other scopes, that will access files same way in same time will need to wait, until scope will be finished.
Usage
This example will try to access file1.json and file2.json, parse them as json, merge its content and write it to file3. On the other hand, second scope will try to write content to file1, so these scopes will never be opened together. Keep in mind, mutex prefix have to be provided with some string, to keep scopes connected together.
await FileScope.prepare('./rootDirectory').open({
a: Dependency.readFileAccess('/dir/dirA/file1.json'),
b: Dependency.readFileAccess('/dir/dirA/file2.json'),
c: Dependency.writeFileAccess('/dir/file3.json'),
}, async (dependecies) => {
const contentA = await dependencies.a.read()
const contentB = await dependencies.b.read()
const jsonA = JSON.parse(contentA)
const jsonB = JSON.parse(contentA)
const newContent = {
...jsonA,
...jsonB,
}
await dependecies.c.write(JSON.stringify(newContent))
})
await FileScope.prepare('./rootDirectory').open({
a: Dependency.writeFileAccess('/dir/dirA/file1.json'),
}, async (dependecies) => {
await dependecies.c.write(JSON.stringify({
hello: 'World from file A',
}))
})
Using dependecies
Dependencies received in first parameter in handler is the same object provided as dependencies when opening scope. FsDependency (created by calling Dependency.readFileAccess
and Dependency.writeFileAccess
) providing few shortcut fuctions, as read/write, unlink, etc... to keep your code shorter. We realy recommending to use dependecies access to simple fs oprations, as we can't change behaviour of fs itself, it will not provides you any safety about access type. In case you will try to write with read access only, it will throw error. Dependency instance can be used only one time in opening scope, as it's connected by fs to scope, where was used. Still you can preapre scope by calling FileScope.prepare()
and open in multiple times, scope itself keeping it's state only insode of open method.
Combining with mutexes
It's internaly using @david.uhlir/mutex to handle it, so it will works in cluster too. You can also lock your scopes as usual using SharedMutex.lockSingleAccess
or SharedMutex.lockMultiAccess
. Key of these mutexes in scope will be generated by this pattern prefix/shortest common path
. Shortest common path means, it will find the lowest folder, which is common for all posible paths. If paths is starting on different point, it will be nested as another lock inside of scope.
Performance
As mutexes are using IPC to synchronize scopes, it can affect performance of your app easily - so it's better, if it's posible, to open less scopes with bigger operations, than a lot of small scopes with easy operations. Still IPC is pretty fast, and in case of application in single process, it will use event emitter, which is even faster.