@inlang/sdk 0.35.3 → 0.35.5

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.
@@ -174,7 +174,7 @@ describe("messages", () => {
174
174
  project.setSettings({ ...project.settings(), languageTags: ["en"] });
175
175
  // TODO: how can we await `setConfig` correctly
176
176
  await new Promise((resolve) => setTimeout(resolve, 510));
177
- expect(effectOnMessagesCounter).toBe(3); // 3 = setSetting, loadMessage (2x - one per message)
177
+ expect(effectOnMessagesCounter).toBe(2); // 2 = setSetting (clearing the message index), subsequencial loadMessage call
178
178
  expect(Object.values(project.query.messages.getAll()).length).toBe(2);
179
179
  });
180
180
  it("should react to message udpate", async () => {
@@ -1 +1 @@
1
- {"version":3,"file":"createMessagesQuery.d.ts","sourceRoot":"","sources":["../src/createMessagesQuery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAyC,MAAM,UAAU,CAAA;AAEpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAInD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AA4B/D,KAAK,6BAA6B,GAAG;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,QAAQ,EAAE,MAAM,eAAe,GAAG,SAAS,CAAA;IAC3C,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,CAAA;IAC7E,0BAA0B,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IAC/C,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IACxC,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;CACxC,CAAA;AACD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,WAAW,EACX,SAAS,EACT,QAAQ,EACR,eAAe,EACf,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACnB,EAAE,6BAA6B,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAmNpE"}
1
+ {"version":3,"file":"createMessagesQuery.d.ts","sourceRoot":"","sources":["../src/createMessagesQuery.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAyC,MAAM,UAAU,CAAA;AAEpF,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qCAAqC,CAAA;AAEzE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAInD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAwB/D,KAAK,6BAA6B,GAAG;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAA;IAC5B,QAAQ,EAAE,MAAM,eAAe,GAAG,SAAS,CAAA;IAC3C,eAAe,EAAE,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,cAAc,CAAC,CAAC,GAAG,SAAS,CAAA;IAC7E,0BAA0B,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IAC/C,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;IACxC,mBAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAA;CACxC,CAAA;AACD;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,EACnC,WAAW,EACX,SAAS,EACT,QAAQ,EACR,eAAe,EACf,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACnB,EAAE,6BAA6B,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAmNpE"}
@@ -1,5 +1,5 @@
1
1
  import { ReactiveMap } from "./reactivity/map.js";
2
- import { createEffect, onCleanup } from "./reactivity/solid.js";
2
+ import { createEffect, onCleanup, batch } from "./reactivity/solid.js";
3
3
  import { createSubscribable } from "./loadProject.js";
4
4
  import { createNodeishFsWithWatcher } from "./createNodeishFsWithWatcher.js";
5
5
  import { stringifyMessage } from "./storage/helper.js";
@@ -9,9 +9,6 @@ import { releaseLock } from "./persistence/filelock/releaseLock.js";
9
9
  import { PluginLoadMessagesError, PluginSaveMessagesError } from "./errors.js";
10
10
  import { humanIdHash } from "./storage/human-id/human-readable-id.js";
11
11
  const debug = _debug("sdk:messages");
12
- function sleep(ms) {
13
- return new Promise((resolve) => setTimeout(resolve, ms));
14
- }
15
12
  /**
16
13
  * Creates a reactive query API for messages.
17
14
  */
@@ -194,7 +191,6 @@ export function createMessagesQuery({ projectPath, nodeishFs, settings, resolved
194
191
  // - json plugin exports into separate file per language.
195
192
  // - saving a message in two different languages would lead to a write in de.json first
196
193
  // - This will leads to a load of the messages and since en.json has not been saved yet the english variant in the message would get overritten with the old state again
197
- const maxMessagesPerTick = 500;
198
194
  /**
199
195
  * Messsage that loads messages from a plugin - this method synchronizes with the saveMessage funciton.
200
196
  * If a save is in progress loading will wait until saving is done. If another load kicks in during this load it will queue the
@@ -227,89 +223,79 @@ async function loadMessagesViaPlugin(fs, lockDirPath, messageState, messages, de
227
223
  settings: settingsValue,
228
224
  nodeishFs: fs,
229
225
  }));
230
- let loadedMessageCount = 0;
231
226
  const deletedMessages = new Set(messages.keys());
232
- for (const loadedMessage of loadedMessages) {
233
- const loadedMessageClone = structuredClone(loadedMessage);
234
- const currentMessages = [...messages.values()]
235
- // TODO #1585 here we match using the id to support legacy load message plugins - after we introduced import / export methods we will use importedMessage.alias
236
- .filter((message) => (experimentalAliases ? message.alias["default"] : message.id) === loadedMessage.id);
237
- if (currentMessages.length > 1) {
238
- // NOTE: if we happen to find two messages witht the sam alias we throw for now
239
- // - this could be the case if one edits the aliase manualy
240
- throw new Error("more than one message with the same id or alias found ");
241
- }
242
- else if (currentMessages.length === 1) {
243
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length has checked beforhand
244
- deletedMessages.delete(currentMessages[0].id);
245
- // update message in place - leave message id and alias untouched
246
- loadedMessageClone.alias = {};
247
- // TODO #1585 we have to map the id of the importedMessage to the alias and fill the id property with the id of the existing message - change when import mesage provides importedMessage.alias
248
- if (experimentalAliases) {
249
- loadedMessageClone.alias["default"] = loadedMessageClone.id;
227
+ batch(() => {
228
+ for (const loadedMessage of loadedMessages) {
229
+ const loadedMessageClone = structuredClone(loadedMessage);
230
+ const currentMessages = [...messages.values()]
231
+ // TODO #1585 here we match using the id to support legacy load message plugins - after we introduced import / export methods we will use importedMessage.alias
232
+ .filter((message) => (experimentalAliases ? message.alias["default"] : message.id) === loadedMessage.id);
233
+ if (currentMessages.length > 1) {
234
+ // NOTE: if we happen to find two messages witht the sam alias we throw for now
235
+ // - this could be the case if one edits the aliase manualy
236
+ throw new Error("more than one message with the same id or alias found ");
237
+ }
238
+ else if (currentMessages.length === 1) {
250
239
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length has checked beforhand
251
- loadedMessageClone.id = currentMessages[0].id;
240
+ deletedMessages.delete(currentMessages[0].id);
241
+ // update message in place - leave message id and alias untouched
242
+ loadedMessageClone.alias = {};
243
+ // TODO #1585 we have to map the id of the importedMessage to the alias and fill the id property with the id of the existing message - change when import mesage provides importedMessage.alias
244
+ if (experimentalAliases) {
245
+ loadedMessageClone.alias["default"] = loadedMessageClone.id;
246
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length has checked beforhand
247
+ loadedMessageClone.id = currentMessages[0].id;
248
+ }
249
+ // NOTE stringifyMessage encodes messages independent from key order!
250
+ const importedEnecoded = stringifyMessage(loadedMessageClone);
251
+ // NOTE could use hash instead of the whole object JSON to save memory...
252
+ if (messageState.messageLoadHash[loadedMessageClone.id] === importedEnecoded) {
253
+ // debug("skipping upsert!")
254
+ continue;
255
+ }
256
+ // This logic is preventing cycles - could also be handled if update api had a parameter for who triggered update
257
+ // e.g. when FS was updated, we don't need to write back to FS
258
+ // update is synchronous, so update effect will be triggered immediately
259
+ // NOTE: this might trigger a save before we have the chance to delete - but since save is async and waits for the lock acquired by this method - its save to set the flags afterwards
260
+ messages.set(loadedMessageClone.id, loadedMessageClone);
261
+ // NOTE could use hash instead of the whole object JSON to save memory...
262
+ messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded;
263
+ delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [
264
+ ...messages.values(),
265
+ ]);
252
266
  }
253
- // NOTE stringifyMessage encodes messages independent from key order!
254
- const importedEnecoded = stringifyMessage(loadedMessageClone);
255
- // NOTE could use hash instead of the whole object JSON to save memory...
256
- if (messageState.messageLoadHash[loadedMessageClone.id] === importedEnecoded) {
257
- // debug("skipping upsert!")
258
- continue;
267
+ else {
268
+ // message with the given alias does not exist so far
269
+ loadedMessageClone.alias = {};
270
+ // TODO #1585 we have to map the id of the importedMessage to the alias - change when import mesage provides importedMessage.alias
271
+ if (experimentalAliases) {
272
+ loadedMessageClone.alias["default"] = loadedMessageClone.id;
273
+ let currentOffset = 0;
274
+ let messsageId;
275
+ do {
276
+ messsageId = humanIdHash(loadedMessageClone.id, currentOffset);
277
+ if (messages.get(messsageId)) {
278
+ currentOffset += 1;
279
+ messsageId = undefined;
280
+ }
281
+ } while (messsageId === undefined);
282
+ // create a humanId based on a hash of the alias
283
+ loadedMessageClone.id = messsageId;
284
+ }
285
+ const importedEnecoded = stringifyMessage(loadedMessageClone);
286
+ // we don't have to check - done before hand if (messages.has(loadedMessageClone.id)) return false
287
+ messages.set(loadedMessageClone.id, loadedMessageClone);
288
+ messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded;
289
+ delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [
290
+ ...messages.values(),
291
+ ]);
259
292
  }
260
- // This logic is preventing cycles - could also be handled if update api had a parameter for who triggered update
261
- // e.g. when FS was updated, we don't need to write back to FS
262
- // update is synchronous, so update effect will be triggered immediately
263
- // NOTE: this might trigger a save before we have the chance to delete - but since save is async and waits for the lock acquired by this method - its save to set the flags afterwards
264
- messages.set(loadedMessageClone.id, loadedMessageClone);
265
- // NOTE could use hash instead of the whole object JSON to save memory...
266
- messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded;
267
- delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [...messages.values()]);
268
- loadedMessageCount++;
269
293
  }
270
- else {
271
- // message with the given alias does not exist so far
272
- loadedMessageClone.alias = {};
273
- // TODO #1585 we have to map the id of the importedMessage to the alias - change when import mesage provides importedMessage.alias
274
- if (experimentalAliases) {
275
- loadedMessageClone.alias["default"] = loadedMessageClone.id;
276
- let currentOffset = 0;
277
- let messsageId;
278
- do {
279
- messsageId = humanIdHash(loadedMessageClone.id, currentOffset);
280
- if (messages.get(messsageId)) {
281
- currentOffset += 1;
282
- messsageId = undefined;
283
- }
284
- } while (messsageId === undefined);
285
- // create a humanId based on a hash of the alias
286
- loadedMessageClone.id = messsageId;
287
- }
288
- const importedEnecoded = stringifyMessage(loadedMessageClone);
289
- // we don't have to check - done before hand if (messages.has(loadedMessageClone.id)) return false
290
- messages.set(loadedMessageClone.id, loadedMessageClone);
291
- messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded;
292
- delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [...messages.values()]);
293
- loadedMessageCount++;
294
+ for (const deletedMessageId of deletedMessages) {
295
+ messages.delete(deletedMessageId);
296
+ delegate?.onMessageDelete(deletedMessageId, [...messages.values()]);
294
297
  }
295
- if (loadedMessageCount > maxMessagesPerTick) {
296
- // move loading of the next messages to the next ticks to allow solid to cleanup resources
297
- // solid needs some time to settle and clean up
298
- // https://github.com/solidjs-community/solid-primitives/blob/9ca76a47ffa2172770e075a90695cf933da0ff48/packages/trigger/src/index.ts#L64
299
- await sleep(0);
300
- loadedMessageCount = 0;
301
- }
302
- }
303
- loadedMessageCount = 0;
304
- for (const deletedMessageId of deletedMessages) {
305
- messages.delete(deletedMessageId);
306
- delegate?.onMessageDelete(deletedMessageId, [...messages.values()]);
307
- loadedMessageCount++;
308
- if (loadedMessageCount > maxMessagesPerTick) {
309
- await sleep(0);
310
- loadedMessageCount = 0;
311
- }
312
- }
298
+ });
313
299
  await releaseLock(fs, lockDirPath, "loadMessage", lockTime);
314
300
  lockTime = undefined;
315
301
  debug("loadMessagesViaPlugin: " + loadedMessages.length + " Messages processed ");
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@inlang/sdk",
3
3
  "type": "module",
4
- "version": "0.35.3",
4
+ "version": "0.35.5",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
7
7
  "access": "public"
@@ -34,15 +34,15 @@
34
34
  "solid-js": "1.6.12",
35
35
  "throttle-debounce": "^5.0.0",
36
36
  "@inlang/json-types": "1.1.0",
37
- "@inlang/language-tag": "1.5.1",
38
37
  "@inlang/message": "2.1.0",
38
+ "@inlang/language-tag": "1.5.1",
39
39
  "@inlang/message-lint-rule": "1.4.7",
40
40
  "@inlang/module": "1.2.13",
41
- "@inlang/project-settings": "2.4.2",
42
41
  "@inlang/plugin": "2.4.13",
43
- "@inlang/result": "1.1.0",
42
+ "@inlang/project-settings": "2.4.2",
44
43
  "@inlang/translatable": "1.3.1",
45
- "@lix-js/client": "2.1.0",
44
+ "@inlang/result": "1.1.0",
45
+ "@lix-js/client": "2.2.0",
46
46
  "@lix-js/fs": "2.1.0"
47
47
  },
48
48
  "devDependencies": {
@@ -222,7 +222,7 @@ describe("messages", () => {
222
222
  // TODO: how can we await `setConfig` correctly
223
223
  await new Promise((resolve) => setTimeout(resolve, 510))
224
224
 
225
- expect(effectOnMessagesCounter).toBe(3) // 3 = setSetting, loadMessage (2x - one per message)
225
+ expect(effectOnMessagesCounter).toBe(2) // 2 = setSetting (clearing the message index), subsequencial loadMessage call
226
226
  expect(Object.values(project.query.messages.getAll()).length).toBe(2)
227
227
  })
228
228
 
@@ -1,6 +1,6 @@
1
1
  import type { Message } from "@inlang/message"
2
2
  import { ReactiveMap } from "./reactivity/map.js"
3
- import { createEffect, onCleanup } from "./reactivity/solid.js"
3
+ import { createEffect, onCleanup, batch } from "./reactivity/solid.js"
4
4
  import { createSubscribable } from "./loadProject.js"
5
5
  import type { InlangProject, MessageQueryApi, MessageQueryDelegate } from "./api.js"
6
6
  import type { ResolvedPluginApi } from "./resolve-modules/plugins/types.js"
@@ -16,10 +16,6 @@ import { PluginLoadMessagesError, PluginSaveMessagesError } from "./errors.js"
16
16
  import { humanIdHash } from "./storage/human-id/human-readable-id.js"
17
17
  const debug = _debug("sdk:messages")
18
18
 
19
- function sleep(ms: number) {
20
- return new Promise((resolve) => setTimeout(resolve, ms))
21
- }
22
-
23
19
  type MessageState = {
24
20
  messageDirtyFlags: {
25
21
  [messageId: string]: boolean
@@ -278,8 +274,6 @@ export function createMessagesQuery({
278
274
  // - saving a message in two different languages would lead to a write in de.json first
279
275
  // - This will leads to a load of the messages and since en.json has not been saved yet the english variant in the message would get overritten with the old state again
280
276
 
281
- const maxMessagesPerTick = 500
282
-
283
277
  /**
284
278
  * Messsage that loads messages from a plugin - this method synchronizes with the saveMessage funciton.
285
279
  * If a save is in progress loading will wait until saving is done. If another load kicks in during this load it will queue the
@@ -326,104 +320,91 @@ async function loadMessagesViaPlugin(
326
320
  })
327
321
  )
328
322
 
329
- let loadedMessageCount = 0
330
-
331
323
  const deletedMessages = new Set(messages.keys())
332
-
333
- for (const loadedMessage of loadedMessages) {
334
- const loadedMessageClone = structuredClone(loadedMessage)
335
-
336
- const currentMessages = [...messages.values()]
337
- // TODO #1585 here we match using the id to support legacy load message plugins - after we introduced import / export methods we will use importedMessage.alias
338
- .filter(
339
- (message: any) =>
340
- (experimentalAliases ? message.alias["default"] : message.id) === loadedMessage.id
341
- )
342
-
343
- if (currentMessages.length > 1) {
344
- // NOTE: if we happen to find two messages witht the sam alias we throw for now
345
- // - this could be the case if one edits the aliase manualy
346
- throw new Error("more than one message with the same id or alias found ")
347
- } else if (currentMessages.length === 1) {
348
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length has checked beforhand
349
- deletedMessages.delete(currentMessages[0]!.id)
350
- // update message in place - leave message id and alias untouched
351
- loadedMessageClone.alias = {} as any
352
-
353
- // TODO #1585 we have to map the id of the importedMessage to the alias and fill the id property with the id of the existing message - change when import mesage provides importedMessage.alias
354
- if (experimentalAliases) {
355
- loadedMessageClone.alias["default"] = loadedMessageClone.id
324
+ batch(() => {
325
+ for (const loadedMessage of loadedMessages) {
326
+ const loadedMessageClone = structuredClone(loadedMessage)
327
+
328
+ const currentMessages = [...messages.values()]
329
+ // TODO #1585 here we match using the id to support legacy load message plugins - after we introduced import / export methods we will use importedMessage.alias
330
+ .filter(
331
+ (message: any) =>
332
+ (experimentalAliases ? message.alias["default"] : message.id) === loadedMessage.id
333
+ )
334
+
335
+ if (currentMessages.length > 1) {
336
+ // NOTE: if we happen to find two messages witht the sam alias we throw for now
337
+ // - this could be the case if one edits the aliase manualy
338
+ throw new Error("more than one message with the same id or alias found ")
339
+ } else if (currentMessages.length === 1) {
356
340
  // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length has checked beforhand
357
- loadedMessageClone.id = currentMessages[0]!.id
341
+ deletedMessages.delete(currentMessages[0]!.id)
342
+ // update message in place - leave message id and alias untouched
343
+ loadedMessageClone.alias = {} as any
344
+
345
+ // TODO #1585 we have to map the id of the importedMessage to the alias and fill the id property with the id of the existing message - change when import mesage provides importedMessage.alias
346
+ if (experimentalAliases) {
347
+ loadedMessageClone.alias["default"] = loadedMessageClone.id
348
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion -- length has checked beforhand
349
+ loadedMessageClone.id = currentMessages[0]!.id
350
+ }
351
+
352
+ // NOTE stringifyMessage encodes messages independent from key order!
353
+ const importedEnecoded = stringifyMessage(loadedMessageClone)
354
+
355
+ // NOTE could use hash instead of the whole object JSON to save memory...
356
+ if (messageState.messageLoadHash[loadedMessageClone.id] === importedEnecoded) {
357
+ // debug("skipping upsert!")
358
+ continue
359
+ }
360
+
361
+ // This logic is preventing cycles - could also be handled if update api had a parameter for who triggered update
362
+ // e.g. when FS was updated, we don't need to write back to FS
363
+ // update is synchronous, so update effect will be triggered immediately
364
+ // NOTE: this might trigger a save before we have the chance to delete - but since save is async and waits for the lock acquired by this method - its save to set the flags afterwards
365
+ messages.set(loadedMessageClone.id, loadedMessageClone)
366
+ // NOTE could use hash instead of the whole object JSON to save memory...
367
+ messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded
368
+ delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [
369
+ ...messages.values(),
370
+ ])
371
+ } else {
372
+ // message with the given alias does not exist so far
373
+ loadedMessageClone.alias = {} as any
374
+ // TODO #1585 we have to map the id of the importedMessage to the alias - change when import mesage provides importedMessage.alias
375
+ if (experimentalAliases) {
376
+ loadedMessageClone.alias["default"] = loadedMessageClone.id
377
+
378
+ let currentOffset = 0
379
+ let messsageId: string | undefined
380
+ do {
381
+ messsageId = humanIdHash(loadedMessageClone.id, currentOffset)
382
+ if (messages.get(messsageId)) {
383
+ currentOffset += 1
384
+ messsageId = undefined
385
+ }
386
+ } while (messsageId === undefined)
387
+
388
+ // create a humanId based on a hash of the alias
389
+ loadedMessageClone.id = messsageId
390
+ }
391
+
392
+ const importedEnecoded = stringifyMessage(loadedMessageClone)
393
+
394
+ // we don't have to check - done before hand if (messages.has(loadedMessageClone.id)) return false
395
+ messages.set(loadedMessageClone.id, loadedMessageClone)
396
+ messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded
397
+ delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [
398
+ ...messages.values(),
399
+ ])
358
400
  }
359
-
360
- // NOTE stringifyMessage encodes messages independent from key order!
361
- const importedEnecoded = stringifyMessage(loadedMessageClone)
362
-
363
- // NOTE could use hash instead of the whole object JSON to save memory...
364
- if (messageState.messageLoadHash[loadedMessageClone.id] === importedEnecoded) {
365
- // debug("skipping upsert!")
366
- continue
367
- }
368
-
369
- // This logic is preventing cycles - could also be handled if update api had a parameter for who triggered update
370
- // e.g. when FS was updated, we don't need to write back to FS
371
- // update is synchronous, so update effect will be triggered immediately
372
- // NOTE: this might trigger a save before we have the chance to delete - but since save is async and waits for the lock acquired by this method - its save to set the flags afterwards
373
- messages.set(loadedMessageClone.id, loadedMessageClone)
374
- // NOTE could use hash instead of the whole object JSON to save memory...
375
- messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded
376
- delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [...messages.values()])
377
- loadedMessageCount++
378
- } else {
379
- // message with the given alias does not exist so far
380
- loadedMessageClone.alias = {} as any
381
- // TODO #1585 we have to map the id of the importedMessage to the alias - change when import mesage provides importedMessage.alias
382
- if (experimentalAliases) {
383
- loadedMessageClone.alias["default"] = loadedMessageClone.id
384
-
385
- let currentOffset = 0
386
- let messsageId: string | undefined
387
- do {
388
- messsageId = humanIdHash(loadedMessageClone.id, currentOffset)
389
- if (messages.get(messsageId)) {
390
- currentOffset += 1
391
- messsageId = undefined
392
- }
393
- } while (messsageId === undefined)
394
-
395
- // create a humanId based on a hash of the alias
396
- loadedMessageClone.id = messsageId
397
- }
398
-
399
- const importedEnecoded = stringifyMessage(loadedMessageClone)
400
-
401
- // we don't have to check - done before hand if (messages.has(loadedMessageClone.id)) return false
402
- messages.set(loadedMessageClone.id, loadedMessageClone)
403
- messageState.messageLoadHash[loadedMessageClone.id] = importedEnecoded
404
- delegate?.onMessageUpdate(loadedMessageClone.id, loadedMessageClone, [...messages.values()])
405
- loadedMessageCount++
406
401
  }
407
- if (loadedMessageCount > maxMessagesPerTick) {
408
- // move loading of the next messages to the next ticks to allow solid to cleanup resources
409
- // solid needs some time to settle and clean up
410
- // https://github.com/solidjs-community/solid-primitives/blob/9ca76a47ffa2172770e075a90695cf933da0ff48/packages/trigger/src/index.ts#L64
411
- await sleep(0)
412
- loadedMessageCount = 0
413
- }
414
- }
415
402
 
416
- loadedMessageCount = 0
417
- for (const deletedMessageId of deletedMessages) {
418
- messages.delete(deletedMessageId)
419
- delegate?.onMessageDelete(deletedMessageId, [...messages.values()])
420
- loadedMessageCount++
421
- if (loadedMessageCount > maxMessagesPerTick) {
422
- await sleep(0)
423
- loadedMessageCount = 0
403
+ for (const deletedMessageId of deletedMessages) {
404
+ messages.delete(deletedMessageId)
405
+ delegate?.onMessageDelete(deletedMessageId, [...messages.values()])
424
406
  }
425
- }
426
-
407
+ })
427
408
  await releaseLock(fs as NodeishFilesystem, lockDirPath, "loadMessage", lockTime)
428
409
  lockTime = undefined
429
410