@inlang/sdk 0.34.3 → 0.34.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/dist/adapter/solidAdapter.test.js +1 -1
- package/dist/createMessagesQuery.d.ts +14 -2
- package/dist/createMessagesQuery.d.ts.map +1 -1
- package/dist/createMessagesQuery.js +338 -6
- package/dist/createMessagesQuery.test.js +133 -88
- package/dist/createNodeishFsWithWatcher.d.ts +1 -0
- package/dist/createNodeishFsWithWatcher.d.ts.map +1 -1
- package/dist/createNodeishFsWithWatcher.js +2 -2
- package/dist/createNodeishFsWithWatcher.test.js +8 -0
- package/dist/loadProject.d.ts.map +1 -1
- package/dist/loadProject.js +21 -487
- package/dist/persistence/filelock/acquireFileLock.d.ts +3 -0
- package/dist/persistence/filelock/acquireFileLock.d.ts.map +1 -0
- package/dist/persistence/filelock/acquireFileLock.js +109 -0
- package/dist/persistence/filelock/releaseLock.d.ts +3 -0
- package/dist/persistence/filelock/releaseLock.d.ts.map +1 -0
- package/dist/persistence/filelock/releaseLock.js +23 -0
- package/package.json +5 -5
- package/src/adapter/solidAdapter.test.ts +1 -1
- package/src/createMessagesQuery.test.ts +147 -109
- package/src/createMessagesQuery.ts +477 -8
- package/src/createNodeishFsWithWatcher.test.ts +13 -0
- package/src/createNodeishFsWithWatcher.ts +2 -2
- package/src/loadProject.ts +20 -666
- package/src/persistence/filelock/acquireFileLock.ts +124 -0
- package/src/persistence/filelock/releaseLock.ts +28 -0
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { type NodeishFilesystem } from "@lix-js/fs"
|
|
2
|
+
import type { NodeishStats } from "@lix-js/fs"
|
|
3
|
+
import _debug from "debug"
|
|
4
|
+
const debug = _debug("sdk:acquireFileLock")
|
|
5
|
+
|
|
6
|
+
const maxRetries = 10
|
|
7
|
+
const nProbes = 50
|
|
8
|
+
const probeInterval = 100
|
|
9
|
+
export async function acquireFileLock(
|
|
10
|
+
fs: NodeishFilesystem,
|
|
11
|
+
lockDirPath: string,
|
|
12
|
+
lockOrigin: string,
|
|
13
|
+
tryCount: number = 0
|
|
14
|
+
): Promise<number> {
|
|
15
|
+
if (tryCount > maxRetries) {
|
|
16
|
+
throw new Error(lockOrigin + " exceeded maximum Retries (5) to acquire lockfile " + tryCount)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
debug(lockOrigin + " tries to acquire a lockfile Retry Nr.: " + tryCount)
|
|
21
|
+
await fs.mkdir(lockDirPath)
|
|
22
|
+
const stats = await fs.stat(lockDirPath)
|
|
23
|
+
debug(lockOrigin + " acquired a lockfile Retry Nr.: " + tryCount)
|
|
24
|
+
return stats.mtimeMs
|
|
25
|
+
} catch (error: any) {
|
|
26
|
+
if (error.code !== "EEXIST") {
|
|
27
|
+
// we only expect the error that the file exists already (locked by other process)
|
|
28
|
+
throw error
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let currentLockTime: number
|
|
33
|
+
|
|
34
|
+
try {
|
|
35
|
+
const stats = await fs.stat(lockDirPath)
|
|
36
|
+
currentLockTime = stats.mtimeMs
|
|
37
|
+
} catch (fstatError: any) {
|
|
38
|
+
if (fstatError.code === "ENOENT") {
|
|
39
|
+
// lock file seems to be gone :) - lets try again
|
|
40
|
+
debug(lockOrigin + " tryCount++ lock file seems to be gone :) - lets try again " + tryCount)
|
|
41
|
+
return acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1)
|
|
42
|
+
}
|
|
43
|
+
throw fstatError
|
|
44
|
+
}
|
|
45
|
+
debug(
|
|
46
|
+
lockOrigin +
|
|
47
|
+
" tries to acquire a lockfile - lock currently in use... starting probe phase " +
|
|
48
|
+
tryCount
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return new Promise((resolve, reject) => {
|
|
52
|
+
let probeCounts = 0
|
|
53
|
+
const scheduleProbationTimeout = () => {
|
|
54
|
+
setTimeout(async () => {
|
|
55
|
+
probeCounts += 1
|
|
56
|
+
let lockFileStats: undefined | NodeishStats = undefined
|
|
57
|
+
try {
|
|
58
|
+
debug(
|
|
59
|
+
lockOrigin + " tries to acquire a lockfile - check if the lock is free now " + tryCount
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
// alright lets give it another try
|
|
63
|
+
lockFileStats = await fs.stat(lockDirPath)
|
|
64
|
+
} catch (fstatError: any) {
|
|
65
|
+
if (fstatError.code === "ENOENT") {
|
|
66
|
+
debug(
|
|
67
|
+
lockOrigin +
|
|
68
|
+
" tryCount++ in Promise - tries to acquire a lockfile - lock file seems to be free now - try to acquire " +
|
|
69
|
+
tryCount
|
|
70
|
+
)
|
|
71
|
+
const lock = acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1)
|
|
72
|
+
return resolve(lock)
|
|
73
|
+
}
|
|
74
|
+
return reject(fstatError)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// still the same locker! -
|
|
78
|
+
if (lockFileStats.mtimeMs === currentLockTime) {
|
|
79
|
+
if (probeCounts >= nProbes) {
|
|
80
|
+
// ok maximum lock time ran up (we waitetd nProbes * probeInterval) - we consider the lock to be stale
|
|
81
|
+
debug(
|
|
82
|
+
lockOrigin +
|
|
83
|
+
" tries to acquire a lockfile - lock not free - but stale lets drop it" +
|
|
84
|
+
tryCount
|
|
85
|
+
)
|
|
86
|
+
try {
|
|
87
|
+
await fs.rmdir(lockDirPath)
|
|
88
|
+
} catch (rmLockError: any) {
|
|
89
|
+
if (rmLockError.code === "ENOENT") {
|
|
90
|
+
// lock already gone?
|
|
91
|
+
// Option 1: The "stale process" decided to get rid of it
|
|
92
|
+
// Option 2: Another process acquiring the lock and detected a stale one as well
|
|
93
|
+
}
|
|
94
|
+
return reject(rmLockError)
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
debug(
|
|
98
|
+
lockOrigin +
|
|
99
|
+
" tryCount++ same locker - try to acquire again after removing stale lock " +
|
|
100
|
+
tryCount
|
|
101
|
+
)
|
|
102
|
+
const lock = await acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1)
|
|
103
|
+
return resolve(lock)
|
|
104
|
+
} catch (lockAquireException) {
|
|
105
|
+
return reject(lockAquireException)
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
// lets schedule a new probation
|
|
109
|
+
return scheduleProbationTimeout()
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
try {
|
|
113
|
+
debug(lockOrigin + " tryCount++ different locker - try to acquire again " + tryCount)
|
|
114
|
+
const lock = await acquireFileLock(fs, lockDirPath, lockOrigin, tryCount + 1)
|
|
115
|
+
return resolve(lock)
|
|
116
|
+
} catch (error) {
|
|
117
|
+
return reject(error)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}, probeInterval)
|
|
121
|
+
}
|
|
122
|
+
scheduleProbationTimeout()
|
|
123
|
+
})
|
|
124
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type NodeishFilesystem } from "@lix-js/fs"
|
|
2
|
+
import _debug from "debug"
|
|
3
|
+
const debug = _debug("sdk:releaseLock")
|
|
4
|
+
|
|
5
|
+
export async function releaseLock(
|
|
6
|
+
fs: NodeishFilesystem,
|
|
7
|
+
lockDirPath: string,
|
|
8
|
+
lockOrigin: string,
|
|
9
|
+
lockTime: number
|
|
10
|
+
) {
|
|
11
|
+
debug(lockOrigin + " releasing the lock ")
|
|
12
|
+
try {
|
|
13
|
+
const stats = await fs.stat(lockDirPath)
|
|
14
|
+
if (stats.mtimeMs === lockTime) {
|
|
15
|
+
// this can be corrupt as welll since the last getStat and the current a modification could have occured :-/
|
|
16
|
+
await fs.rmdir(lockDirPath)
|
|
17
|
+
}
|
|
18
|
+
} catch (statError: any) {
|
|
19
|
+
debug(lockOrigin + " couldn't release the lock")
|
|
20
|
+
if (statError.code === "ENOENT") {
|
|
21
|
+
// ok seeks like the log was released by someone else
|
|
22
|
+
debug(lockOrigin + " WARNING - the lock was released by a different process")
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
debug(statError)
|
|
26
|
+
throw statError
|
|
27
|
+
}
|
|
28
|
+
}
|