@portel/photon-core 2.19.0 → 2.19.2
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/dist/dependency-manager.d.ts.map +1 -1
- package/dist/dependency-manager.js +1 -2
- package/dist/dependency-manager.js.map +1 -1
- package/dist/memory.d.ts +8 -4
- package/dist/memory.d.ts.map +1 -1
- package/dist/memory.js +82 -36
- package/dist/memory.js.map +1 -1
- package/package.json +1 -1
- package/src/dependency-manager.ts +1 -2
- package/src/memory.ts +79 -32
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-manager.d.ts","sourceRoot":"","sources":["../src/dependency-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,CAAC,EAAE,MAAM;IAI7B;;;;;;OAMG;IACG,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA0C5E;;;;OAIG;IACG,kBAAkB,CACtB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,cAAc,EAAE,GAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA6CzB;;OAEG;YACW,cAAc;IA0C5B;;OAEG;YACW,aAAa;
|
|
1
|
+
{"version":3,"file":"dependency-manager.d.ts","sourceRoot":"","sources":["../src/dependency-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,UAAU,cAAc;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;GAEG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,CAAC,EAAE,MAAM;IAI7B;;;;;;OAMG;IACG,mBAAmB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA0C5E;;;;OAIG;IACG,kBAAkB,CACtB,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,cAAc,EAAE,GAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IA6CzB;;OAEG;YACW,cAAc;IA0C5B;;OAEG;YACW,aAAa;IAkB3B;;;;;;;;;;OAUG;YACW,uBAAuB;IA0CrC;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhD;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;CAQrC"}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from 'fs/promises';
|
|
8
8
|
import * as path from 'path';
|
|
9
|
-
import { spawn } from 'child_process';
|
|
9
|
+
import { spawn, execSync } from 'child_process';
|
|
10
10
|
import { fileURLToPath } from 'url';
|
|
11
11
|
import { getCacheDir } from './data-paths.js';
|
|
12
12
|
/**
|
|
@@ -135,7 +135,6 @@ export class DependencyManager {
|
|
|
135
135
|
* Run package install in a directory (bun or npm)
|
|
136
136
|
*/
|
|
137
137
|
async runNpmInstall(cwd) {
|
|
138
|
-
const { execSync } = require('child_process');
|
|
139
138
|
const hasBun = (() => { try {
|
|
140
139
|
execSync('bun --version', { stdio: 'ignore' });
|
|
141
140
|
return true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dependency-manager.js","sourceRoot":"","sources":["../src/dependency-manager.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"dependency-manager.js","sourceRoot":"","sources":["../src/dependency-manager.ts"],"names":[],"mappings":"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"}
|
package/dist/memory.d.ts
CHANGED
|
@@ -35,7 +35,13 @@ export declare class MemoryProvider {
|
|
|
35
35
|
private _namespace;
|
|
36
36
|
private _sessionId?;
|
|
37
37
|
private _baseDir?;
|
|
38
|
+
private _locks;
|
|
38
39
|
constructor(photonId: string, sessionId?: string, namespace?: string, baseDir?: string);
|
|
40
|
+
/**
|
|
41
|
+
* Serialize file operations per key to prevent concurrent write corruption.
|
|
42
|
+
* Reads also go through the lock to avoid reading a partially-written file.
|
|
43
|
+
*/
|
|
44
|
+
private withKeyLock;
|
|
39
45
|
/**
|
|
40
46
|
* Current session ID (can be updated by the runtime)
|
|
41
47
|
*/
|
|
@@ -91,10 +97,8 @@ export declare class MemoryProvider {
|
|
|
91
97
|
*/
|
|
92
98
|
getAll<T = any>(scope?: MemoryScope): Promise<Record<string, T>>;
|
|
93
99
|
/**
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* Note: Not truly atomic under concurrent access. For concurrent
|
|
97
|
-
* writes, use distributed locking via `withLock()`.
|
|
100
|
+
* Atomic read-modify-write for a key.
|
|
101
|
+
* Serialized per key so concurrent updates don't corrupt data.
|
|
98
102
|
*
|
|
99
103
|
* @param key The key to update
|
|
100
104
|
* @param updater Function that receives current value and returns new value
|
package/dist/memory.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAeH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAmE1D;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,CAAS;
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAeH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAC;AAmE1D;;;;;GAKG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,UAAU,CAAC,CAAS;IAC5B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAoC;gBAEtC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM;IAOtF;;;OAGG;YACW,WAAW;IAiBzB;;OAEG;IACH,IAAI,SAAS,IAAI,MAAM,GAAG,SAAS,CAElC;IAED,IAAI,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,EAEnC;IAED;;;;;;OAMG;IACG,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,WAAsB,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC;IAejF;;;;;;OAMG;IACG,GAAG,CAAC,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,KAAK,GAAE,WAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvF;;;;;;OAMG;IACG,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,WAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IAe1E;;;;;OAKG;IACG,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,GAAE,WAAsB,GAAG,OAAO,CAAC,OAAO,CAAC;IAKvE;;;;OAIG;IACG,IAAI,CAAC,KAAK,GAAE,WAAsB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAc5D;;;;OAIG;IACG,KAAK,CAAC,KAAK,GAAE,WAAsB,GAAG,OAAO,CAAC,IAAI,CAAC;IAazD;;;;OAIG;IACG,MAAM,CAAC,CAAC,GAAG,GAAG,EAAE,KAAK,GAAE,WAAsB,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IAchF;;;;;;;OAOG;IACG,MAAM,CAAC,CAAC,GAAG,GAAG,EAClB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,KAAK,CAAC,EACjC,KAAK,GAAE,WAAsB,GAC5B,OAAO,CAAC,CAAC,CAAC;CAwBd"}
|
package/dist/memory.js
CHANGED
|
@@ -98,12 +98,34 @@ export class MemoryProvider {
|
|
|
98
98
|
_namespace;
|
|
99
99
|
_sessionId;
|
|
100
100
|
_baseDir;
|
|
101
|
+
_locks = new Map();
|
|
101
102
|
constructor(photonId, sessionId, namespace, baseDir) {
|
|
102
103
|
this._photonId = photonId;
|
|
103
104
|
this._namespace = namespace || 'local';
|
|
104
105
|
this._sessionId = sessionId;
|
|
105
106
|
this._baseDir = baseDir;
|
|
106
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Serialize file operations per key to prevent concurrent write corruption.
|
|
110
|
+
* Reads also go through the lock to avoid reading a partially-written file.
|
|
111
|
+
*/
|
|
112
|
+
async withKeyLock(key, scope, fn) {
|
|
113
|
+
const lockKey = `${scope}:${key}`;
|
|
114
|
+
const prev = this._locks.get(lockKey) ?? Promise.resolve();
|
|
115
|
+
let resolve;
|
|
116
|
+
const next = new Promise(r => { resolve = r; });
|
|
117
|
+
this._locks.set(lockKey, next);
|
|
118
|
+
try {
|
|
119
|
+
await prev;
|
|
120
|
+
return await fn();
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
resolve();
|
|
124
|
+
if (this._locks.get(lockKey) === next) {
|
|
125
|
+
this._locks.delete(lockKey);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
107
129
|
/**
|
|
108
130
|
* Current session ID (can be updated by the runtime)
|
|
109
131
|
*/
|
|
@@ -121,17 +143,19 @@ export class MemoryProvider {
|
|
|
121
143
|
* @returns The stored value, or null if not found
|
|
122
144
|
*/
|
|
123
145
|
async get(key, scope = 'photon') {
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
146
|
+
return this.withKeyLock(key, scope, async () => {
|
|
147
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
148
|
+
const filePath = keyPath(dir, key);
|
|
149
|
+
try {
|
|
150
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
151
|
+
return JSON.parse(content);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (error.code === 'ENOENT')
|
|
155
|
+
return null;
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
});
|
|
135
159
|
}
|
|
136
160
|
/**
|
|
137
161
|
* Set a value in memory
|
|
@@ -141,12 +165,17 @@ export class MemoryProvider {
|
|
|
141
165
|
* @param scope Storage scope (default: 'photon')
|
|
142
166
|
*/
|
|
143
167
|
async set(key, value, scope = 'photon') {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
await
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
168
|
+
return this.withKeyLock(key, scope, async () => {
|
|
169
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
170
|
+
if (!await pathExists(dir)) {
|
|
171
|
+
await fs.mkdir(dir, { recursive: true });
|
|
172
|
+
}
|
|
173
|
+
const filePath = keyPath(dir, key);
|
|
174
|
+
// Write to temp file then rename for atomic replacement
|
|
175
|
+
const tmpPath = filePath + '.tmp';
|
|
176
|
+
await fs.writeFile(tmpPath, JSON.stringify(value, null, 2));
|
|
177
|
+
await fs.rename(tmpPath, filePath);
|
|
178
|
+
});
|
|
150
179
|
}
|
|
151
180
|
/**
|
|
152
181
|
* Delete a key from memory
|
|
@@ -156,17 +185,19 @@ export class MemoryProvider {
|
|
|
156
185
|
* @returns true if the key existed and was deleted
|
|
157
186
|
*/
|
|
158
187
|
async delete(key, scope = 'photon') {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
188
|
+
return this.withKeyLock(key, scope, async () => {
|
|
189
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
190
|
+
const filePath = keyPath(dir, key);
|
|
191
|
+
try {
|
|
192
|
+
await fs.unlink(filePath);
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
catch (error) {
|
|
196
|
+
if (error.code === 'ENOENT')
|
|
197
|
+
return false;
|
|
198
|
+
throw error;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
170
201
|
}
|
|
171
202
|
/**
|
|
172
203
|
* Check if a key exists in memory
|
|
@@ -232,20 +263,35 @@ export class MemoryProvider {
|
|
|
232
263
|
return result;
|
|
233
264
|
}
|
|
234
265
|
/**
|
|
235
|
-
*
|
|
236
|
-
*
|
|
237
|
-
* Note: Not truly atomic under concurrent access. For concurrent
|
|
238
|
-
* writes, use distributed locking via `withLock()`.
|
|
266
|
+
* Atomic read-modify-write for a key.
|
|
267
|
+
* Serialized per key so concurrent updates don't corrupt data.
|
|
239
268
|
*
|
|
240
269
|
* @param key The key to update
|
|
241
270
|
* @param updater Function that receives current value and returns new value
|
|
242
271
|
* @param scope Storage scope (default: 'photon')
|
|
243
272
|
*/
|
|
244
273
|
async update(key, updater, scope = 'photon') {
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
274
|
+
return this.withKeyLock(key, scope, async () => {
|
|
275
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
276
|
+
const filePath = keyPath(dir, key);
|
|
277
|
+
let current = null;
|
|
278
|
+
try {
|
|
279
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
280
|
+
current = JSON.parse(content);
|
|
281
|
+
}
|
|
282
|
+
catch (error) {
|
|
283
|
+
if (error.code !== 'ENOENT')
|
|
284
|
+
throw error;
|
|
285
|
+
}
|
|
286
|
+
const updated = updater(current);
|
|
287
|
+
if (!await pathExists(dir)) {
|
|
288
|
+
await fs.mkdir(dir, { recursive: true });
|
|
289
|
+
}
|
|
290
|
+
const tmpPath = filePath + '.tmp';
|
|
291
|
+
await fs.writeFile(tmpPath, JSON.stringify(updated, null, 2));
|
|
292
|
+
await fs.rename(tmpPath, filePath);
|
|
293
|
+
return updated;
|
|
294
|
+
});
|
|
249
295
|
}
|
|
250
296
|
}
|
|
251
297
|
//# sourceMappingURL=memory.js.map
|
package/dist/memory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,MAAM,MAAM,IAAI,CAAC;AAC7B,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,EACnB,kBAAkB,EAClB,wBAAwB,EACxB,yBAAyB,GAC1B,MAAM,iBAAiB,CAAC;AAIzB;;;GAGG;AACH,SAAS,UAAU,CACjB,QAAgB,EAChB,SAAiB,EACjB,KAAkB,EAClB,SAAkB,EAClB,OAAgB;IAEhB,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAChE,0DAA0D;YAC1D,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,kBAAkB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACxD,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,OAAO,SAAS,CAAC;YACrD,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,KAAK,SAAS,CAAC,CAAC,CAAC;YACf,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CAAC,0EAA0E,CAAC,CAAC;YAC9F,CAAC;YACD,MAAM,MAAM,GAAG,mBAAmB,CAAC,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC5E,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,yBAAyB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC1E,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,OAAO,SAAS,CAAC;YACrD,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,MAAM,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC/B,MAAM,SAAS,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;gBACpD,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;oBAAE,OAAO,SAAS,CAAC;YACrD,CAAC;YACD,OAAO,MAAM,CAAC;QAChB,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,yBAAyB,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,OAAO,CAAC,GAAW,EAAE,GAAW;IACvC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC;IACrD,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,OAAO,CAAC,CAAC;AAC3C,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,UAAU,CAAC,CAAS;IACjC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,OAAO,cAAc;IACjB,SAAS,CAAS;IAClB,UAAU,CAAS;IACnB,UAAU,CAAU;IACpB,QAAQ,CAAU;
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../src/memory.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@portel/photon-core",
|
|
3
|
-
"version": "2.19.
|
|
3
|
+
"version": "2.19.2",
|
|
4
4
|
"description": "Core library for parsing, loading, and managing .photon.ts files - runtime-agnostic foundation for building custom Photon runtimes",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
import * as fs from 'fs/promises';
|
|
9
9
|
import * as path from 'path';
|
|
10
|
-
import { spawn } from 'child_process';
|
|
10
|
+
import { spawn, execSync } from 'child_process';
|
|
11
11
|
import { fileURLToPath } from 'url';
|
|
12
12
|
import { getCacheDir } from './data-paths.js';
|
|
13
13
|
|
|
@@ -177,7 +177,6 @@ export class DependencyManager {
|
|
|
177
177
|
* Run package install in a directory (bun or npm)
|
|
178
178
|
*/
|
|
179
179
|
private async runNpmInstall(cwd: string): Promise<void> {
|
|
180
|
-
const { execSync } = require('child_process');
|
|
181
180
|
const hasBun = (() => { try { execSync('bun --version', { stdio: 'ignore' }); return true; } catch { return false; } })();
|
|
182
181
|
const cmd = hasBun ? 'bun' : (process.platform === 'win32' ? 'npm.cmd' : 'npm');
|
|
183
182
|
const args = hasBun ? ['install'] : ['install', '--omit=dev', '--silent'];
|
package/src/memory.ts
CHANGED
|
@@ -115,6 +115,7 @@ export class MemoryProvider {
|
|
|
115
115
|
private _namespace: string;
|
|
116
116
|
private _sessionId?: string;
|
|
117
117
|
private _baseDir?: string;
|
|
118
|
+
private _locks = new Map<string, Promise<void>>();
|
|
118
119
|
|
|
119
120
|
constructor(photonId: string, sessionId?: string, namespace?: string, baseDir?: string) {
|
|
120
121
|
this._photonId = photonId;
|
|
@@ -123,6 +124,27 @@ export class MemoryProvider {
|
|
|
123
124
|
this._baseDir = baseDir;
|
|
124
125
|
}
|
|
125
126
|
|
|
127
|
+
/**
|
|
128
|
+
* Serialize file operations per key to prevent concurrent write corruption.
|
|
129
|
+
* Reads also go through the lock to avoid reading a partially-written file.
|
|
130
|
+
*/
|
|
131
|
+
private async withKeyLock<T>(key: string, scope: MemoryScope, fn: () => Promise<T>): Promise<T> {
|
|
132
|
+
const lockKey = `${scope}:${key}`;
|
|
133
|
+
const prev = this._locks.get(lockKey) ?? Promise.resolve();
|
|
134
|
+
let resolve!: () => void;
|
|
135
|
+
const next = new Promise<void>(r => { resolve = r; });
|
|
136
|
+
this._locks.set(lockKey, next);
|
|
137
|
+
try {
|
|
138
|
+
await prev;
|
|
139
|
+
return await fn();
|
|
140
|
+
} finally {
|
|
141
|
+
resolve();
|
|
142
|
+
if (this._locks.get(lockKey) === next) {
|
|
143
|
+
this._locks.delete(lockKey);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
126
148
|
/**
|
|
127
149
|
* Current session ID (can be updated by the runtime)
|
|
128
150
|
*/
|
|
@@ -142,16 +164,18 @@ export class MemoryProvider {
|
|
|
142
164
|
* @returns The stored value, or null if not found
|
|
143
165
|
*/
|
|
144
166
|
async get<T = any>(key: string, scope: MemoryScope = 'photon'): Promise<T | null> {
|
|
145
|
-
|
|
146
|
-
|
|
167
|
+
return this.withKeyLock(key, scope, async () => {
|
|
168
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
169
|
+
const filePath = keyPath(dir, key);
|
|
147
170
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
171
|
+
try {
|
|
172
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
173
|
+
return JSON.parse(content) as T;
|
|
174
|
+
} catch (error: any) {
|
|
175
|
+
if (error.code === 'ENOENT') return null;
|
|
176
|
+
throw error;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
155
179
|
}
|
|
156
180
|
|
|
157
181
|
/**
|
|
@@ -162,14 +186,19 @@ export class MemoryProvider {
|
|
|
162
186
|
* @param scope Storage scope (default: 'photon')
|
|
163
187
|
*/
|
|
164
188
|
async set<T = any>(key: string, value: T, scope: MemoryScope = 'photon'): Promise<void> {
|
|
165
|
-
|
|
189
|
+
return this.withKeyLock(key, scope, async () => {
|
|
190
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
166
191
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
192
|
+
if (!await pathExists(dir)) {
|
|
193
|
+
await fs.mkdir(dir, { recursive: true });
|
|
194
|
+
}
|
|
170
195
|
|
|
171
|
-
|
|
172
|
-
|
|
196
|
+
const filePath = keyPath(dir, key);
|
|
197
|
+
// Write to temp file then rename for atomic replacement
|
|
198
|
+
const tmpPath = filePath + '.tmp';
|
|
199
|
+
await fs.writeFile(tmpPath, JSON.stringify(value, null, 2));
|
|
200
|
+
await fs.rename(tmpPath, filePath);
|
|
201
|
+
});
|
|
173
202
|
}
|
|
174
203
|
|
|
175
204
|
/**
|
|
@@ -180,16 +209,18 @@ export class MemoryProvider {
|
|
|
180
209
|
* @returns true if the key existed and was deleted
|
|
181
210
|
*/
|
|
182
211
|
async delete(key: string, scope: MemoryScope = 'photon'): Promise<boolean> {
|
|
183
|
-
|
|
184
|
-
|
|
212
|
+
return this.withKeyLock(key, scope, async () => {
|
|
213
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
214
|
+
const filePath = keyPath(dir, key);
|
|
185
215
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
216
|
+
try {
|
|
217
|
+
await fs.unlink(filePath);
|
|
218
|
+
return true;
|
|
219
|
+
} catch (error: any) {
|
|
220
|
+
if (error.code === 'ENOENT') return false;
|
|
221
|
+
throw error;
|
|
222
|
+
}
|
|
223
|
+
});
|
|
193
224
|
}
|
|
194
225
|
|
|
195
226
|
/**
|
|
@@ -260,10 +291,8 @@ export class MemoryProvider {
|
|
|
260
291
|
}
|
|
261
292
|
|
|
262
293
|
/**
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
* Note: Not truly atomic under concurrent access. For concurrent
|
|
266
|
-
* writes, use distributed locking via `withLock()`.
|
|
294
|
+
* Atomic read-modify-write for a key.
|
|
295
|
+
* Serialized per key so concurrent updates don't corrupt data.
|
|
267
296
|
*
|
|
268
297
|
* @param key The key to update
|
|
269
298
|
* @param updater Function that receives current value and returns new value
|
|
@@ -274,9 +303,27 @@ export class MemoryProvider {
|
|
|
274
303
|
updater: (current: T | null) => T,
|
|
275
304
|
scope: MemoryScope = 'photon'
|
|
276
305
|
): Promise<T> {
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
306
|
+
return this.withKeyLock(key, scope, async () => {
|
|
307
|
+
const dir = resolveDir(this._photonId, this._namespace, scope, this._sessionId, this._baseDir);
|
|
308
|
+
const filePath = keyPath(dir, key);
|
|
309
|
+
|
|
310
|
+
let current: T | null = null;
|
|
311
|
+
try {
|
|
312
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
313
|
+
current = JSON.parse(content) as T;
|
|
314
|
+
} catch (error: any) {
|
|
315
|
+
if (error.code !== 'ENOENT') throw error;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
const updated = updater(current);
|
|
319
|
+
|
|
320
|
+
if (!await pathExists(dir)) {
|
|
321
|
+
await fs.mkdir(dir, { recursive: true });
|
|
322
|
+
}
|
|
323
|
+
const tmpPath = filePath + '.tmp';
|
|
324
|
+
await fs.writeFile(tmpPath, JSON.stringify(updated, null, 2));
|
|
325
|
+
await fs.rename(tmpPath, filePath);
|
|
326
|
+
return updated;
|
|
327
|
+
});
|
|
281
328
|
}
|
|
282
329
|
}
|