@voidhash/mimic-effect 1.0.0-beta.16 → 1.0.0-beta.17

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.
Files changed (99) hide show
  1. package/dist/ColdStorage.cjs +1 -1
  2. package/dist/ColdStorage.d.cts +2 -2
  3. package/dist/ColdStorage.d.cts.map +1 -1
  4. package/dist/ColdStorage.d.mts +2 -2
  5. package/dist/ColdStorage.d.mts.map +1 -1
  6. package/dist/ColdStorage.mjs +2 -2
  7. package/dist/ColdStorage.mjs.map +1 -1
  8. package/dist/DocumentInstance.cjs +13 -13
  9. package/dist/DocumentInstance.mjs +13 -13
  10. package/dist/DocumentInstance.mjs.map +1 -1
  11. package/dist/Errors.d.cts +8 -8
  12. package/dist/Errors.d.cts.map +1 -1
  13. package/dist/Errors.d.mts +8 -8
  14. package/dist/Errors.d.mts.map +1 -1
  15. package/dist/HotStorage.cjs +1 -1
  16. package/dist/HotStorage.d.cts +2 -2
  17. package/dist/HotStorage.d.mts +2 -2
  18. package/dist/HotStorage.mjs +2 -2
  19. package/dist/HotStorage.mjs.map +1 -1
  20. package/dist/Metrics.cjs +6 -6
  21. package/dist/Metrics.d.cts +21 -23
  22. package/dist/Metrics.d.cts.map +1 -1
  23. package/dist/Metrics.d.mts +21 -23
  24. package/dist/Metrics.d.mts.map +1 -1
  25. package/dist/Metrics.mjs +7 -7
  26. package/dist/Metrics.mjs.map +1 -1
  27. package/dist/MimicAuthService.cjs +1 -1
  28. package/dist/MimicAuthService.d.cts +2 -2
  29. package/dist/MimicAuthService.d.cts.map +1 -1
  30. package/dist/MimicAuthService.d.mts +2 -2
  31. package/dist/MimicAuthService.d.mts.map +1 -1
  32. package/dist/MimicAuthService.mjs +2 -2
  33. package/dist/MimicAuthService.mjs.map +1 -1
  34. package/dist/MimicClusterServerEngine.cjs +38 -41
  35. package/dist/MimicClusterServerEngine.d.cts +1 -1
  36. package/dist/MimicClusterServerEngine.d.mts +1 -1
  37. package/dist/MimicClusterServerEngine.mjs +31 -34
  38. package/dist/MimicClusterServerEngine.mjs.map +1 -1
  39. package/dist/MimicServer.cjs +23 -23
  40. package/dist/MimicServer.d.cts +3 -3
  41. package/dist/MimicServer.d.cts.map +1 -1
  42. package/dist/MimicServer.d.mts +3 -3
  43. package/dist/MimicServer.d.mts.map +1 -1
  44. package/dist/MimicServer.mjs +22 -22
  45. package/dist/MimicServer.mjs.map +1 -1
  46. package/dist/MimicServerEngine.cjs +13 -13
  47. package/dist/MimicServerEngine.d.cts +2 -2
  48. package/dist/MimicServerEngine.d.mts +2 -2
  49. package/dist/MimicServerEngine.mjs +14 -14
  50. package/dist/MimicServerEngine.mjs.map +1 -1
  51. package/dist/PresenceManager.cjs +4 -4
  52. package/dist/PresenceManager.d.cts +2 -2
  53. package/dist/PresenceManager.d.mts +2 -2
  54. package/dist/PresenceManager.mjs +5 -5
  55. package/dist/PresenceManager.mjs.map +1 -1
  56. package/dist/Types.d.cts +1 -1
  57. package/dist/Types.d.mts +1 -1
  58. package/dist/testing/ColdStorageTestSuite.cjs +3 -3
  59. package/dist/testing/ColdStorageTestSuite.mjs +3 -3
  60. package/dist/testing/ColdStorageTestSuite.mjs.map +1 -1
  61. package/dist/testing/HotStorageTestSuite.cjs +13 -13
  62. package/dist/testing/HotStorageTestSuite.mjs +13 -13
  63. package/dist/testing/HotStorageTestSuite.mjs.map +1 -1
  64. package/dist/testing/StorageIntegrationTestSuite.cjs +3 -3
  65. package/dist/testing/StorageIntegrationTestSuite.mjs +3 -3
  66. package/dist/testing/StorageIntegrationTestSuite.mjs.map +1 -1
  67. package/dist/testing/types.d.cts +1 -1
  68. package/dist/testing/types.d.cts.map +1 -1
  69. package/dist/testing/types.d.mts +3 -3
  70. package/dist/testing/types.d.mts.map +1 -1
  71. package/package.json +17 -21
  72. package/src/ColdStorage.ts +4 -5
  73. package/src/DocumentInstance.ts +13 -13
  74. package/src/HotStorage.ts +3 -3
  75. package/src/Metrics.ts +22 -16
  76. package/src/MimicAuthService.ts +3 -3
  77. package/src/MimicClusterServerEngine.ts +35 -35
  78. package/src/MimicServer.ts +26 -30
  79. package/src/MimicServerEngine.ts +15 -15
  80. package/src/PresenceManager.ts +6 -6
  81. package/src/Types.ts +1 -1
  82. package/src/testing/ColdStorageTestSuite.ts +3 -3
  83. package/src/testing/HotStorageTestSuite.ts +17 -17
  84. package/src/testing/StorageIntegrationTestSuite.ts +3 -3
  85. package/.turbo/turbo-build.log +0 -154
  86. package/tests/ColdStorage.test.ts +0 -24
  87. package/tests/DocumentInstance.test.ts +0 -669
  88. package/tests/HotStorage.test.ts +0 -24
  89. package/tests/MimicAuthService.test.ts +0 -153
  90. package/tests/MimicClusterServerEngine.test.ts +0 -587
  91. package/tests/MimicServer.test.ts +0 -142
  92. package/tests/MimicServerEngine.test.ts +0 -547
  93. package/tests/PresenceManager.test.ts +0 -380
  94. package/tests/Protocol.test.ts +0 -190
  95. package/tests/StorageIntegration.test.ts +0 -259
  96. package/tsconfig.build.json +0 -24
  97. package/tsconfig.json +0 -8
  98. package/tsdown.config.ts +0 -18
  99. package/vitest.mts +0 -11
@@ -5,8 +5,8 @@ const require_DocumentInstance = require('./DocumentInstance.cjs');
5
5
  const require_objectSpread2 = require('./_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.cjs');
6
6
  const require_MimicServerEngine = require('./MimicServerEngine.cjs');
7
7
  let effect = require("effect");
8
- let _effect_cluster = require("@effect/cluster");
9
- let _effect_rpc = require("@effect/rpc");
8
+ let effect_unstable_cluster = require("effect/unstable/cluster");
9
+ let effect_unstable_rpc = require("effect/unstable/rpc");
10
10
 
11
11
  //#region src/MimicClusterServerEngine.ts
12
12
  /**
@@ -28,90 +28,87 @@ const DEFAULT_SHARD_GROUP = "mimic-documents";
28
28
  */
29
29
  const EncodedTransactionSchema = effect.Schema.Struct({
30
30
  id: effect.Schema.String,
31
- ops: effect.Schema.Array(effect.Schema.Unknown)
31
+ ops: effect.Schema.Array(effect.Schema.Any)
32
32
  });
33
33
  /**
34
34
  * Schema for submit result
35
35
  */
36
- const SubmitResultSchema = effect.Schema.Union(effect.Schema.Struct({
36
+ const SubmitResultSchema = effect.Schema.Union([effect.Schema.Struct({
37
37
  success: effect.Schema.Literal(true),
38
38
  version: effect.Schema.Number
39
39
  }), effect.Schema.Struct({
40
40
  success: effect.Schema.Literal(false),
41
41
  reason: effect.Schema.String
42
- }));
42
+ })]);
43
43
  /**
44
44
  * Schema for snapshot response
45
45
  */
46
46
  const SnapshotResponseSchema = effect.Schema.Struct({
47
- state: effect.Schema.Unknown,
47
+ state: effect.Schema.Any,
48
48
  version: effect.Schema.Number
49
49
  });
50
50
  /**
51
51
  * Schema for presence entry
52
52
  */
53
53
  const PresenceEntrySchema = effect.Schema.Struct({
54
- data: effect.Schema.Unknown,
54
+ data: effect.Schema.Any,
55
55
  userId: effect.Schema.optional(effect.Schema.String)
56
56
  });
57
57
  /**
58
58
  * Schema for presence snapshot response
59
59
  */
60
- const PresenceSnapshotResponseSchema = effect.Schema.Struct({ presences: effect.Schema.Record({
61
- key: effect.Schema.String,
62
- value: PresenceEntrySchema
63
- }) });
64
- effect.Schema.Union(effect.Schema.Struct({
60
+ const PresenceSnapshotResponseSchema = effect.Schema.Struct({ presences: effect.Schema.Record(effect.Schema.String, PresenceEntrySchema) });
61
+ effect.Schema.Union([effect.Schema.Struct({
65
62
  type: effect.Schema.Literal("presence_update"),
66
63
  id: effect.Schema.String,
67
- data: effect.Schema.Unknown,
64
+ data: effect.Schema.Any,
68
65
  userId: effect.Schema.optional(effect.Schema.String)
69
66
  }), effect.Schema.Struct({
70
67
  type: effect.Schema.Literal("presence_remove"),
71
68
  id: effect.Schema.String
72
- }));
73
- effect.Schema.Unknown;
69
+ })]);
70
+ effect.Schema.Any;
74
71
  /**
75
72
  * Define the Mimic Document Entity with its RPC protocol.
76
73
  * This entity handles document operations for a single documentId.
77
74
  */
78
- const MimicDocumentEntity = _effect_cluster.Entity.make("MimicDocument", [
79
- _effect_rpc.Rpc.make("Submit", {
75
+ const MimicDocumentEntity = effect_unstable_cluster.Entity.make("MimicDocument", [
76
+ effect_unstable_rpc.Rpc.make("Submit", {
80
77
  payload: { transaction: EncodedTransactionSchema },
81
78
  success: SubmitResultSchema
82
79
  }),
83
- _effect_rpc.Rpc.make("GetSnapshot", { success: SnapshotResponseSchema }),
84
- _effect_rpc.Rpc.make("GetTreeSnapshot", { success: effect.Schema.Unknown }),
85
- _effect_rpc.Rpc.make("Touch", { success: effect.Schema.Void }),
86
- _effect_rpc.Rpc.make("SetPresence", {
80
+ effect_unstable_rpc.Rpc.make("GetSnapshot", { success: SnapshotResponseSchema }),
81
+ effect_unstable_rpc.Rpc.make("GetTreeSnapshot", { success: effect.Schema.Any }),
82
+ effect_unstable_rpc.Rpc.make("Touch", { success: effect.Schema.Void }),
83
+ effect_unstable_rpc.Rpc.make("SetPresence", {
87
84
  payload: {
88
85
  connectionId: effect.Schema.String,
89
86
  entry: PresenceEntrySchema
90
87
  },
91
88
  success: effect.Schema.Void
92
89
  }),
93
- _effect_rpc.Rpc.make("RemovePresence", {
90
+ effect_unstable_rpc.Rpc.make("RemovePresence", {
94
91
  payload: { connectionId: effect.Schema.String },
95
92
  success: effect.Schema.Void
96
93
  }),
97
- _effect_rpc.Rpc.make("GetPresenceSnapshot", { success: PresenceSnapshotResponseSchema })
94
+ effect_unstable_rpc.Rpc.make("GetPresenceSnapshot", { success: PresenceSnapshotResponseSchema })
98
95
  ]);
99
96
  /**
100
97
  * Context tag for cluster engine configuration
101
98
  */
102
- var MimicClusterConfigTag = class extends effect.Context.Tag("@voidhash/mimic-effect/MimicClusterConfig")() {};
99
+ var MimicClusterConfigTag = class extends effect.ServiceMap.Service()("@voidhash/mimic-effect/MimicClusterConfig") {};
103
100
  const resolveClusterConfig = (config) => {
104
101
  var _config$maxTransactio, _config$snapshot, _config$snapshot$tran, _config$snapshot2, _config$snapshot3, _config$shardGroup;
105
102
  return {
106
103
  schema: config.schema,
107
104
  initial: config.initial,
108
105
  presence: config.presence,
109
- maxIdleTime: config.maxIdleTime ? effect.Duration.decode(config.maxIdleTime) : DEFAULT_MAX_IDLE_TIME,
106
+ maxIdleTime: config.maxIdleTime ? effect.Duration.fromInputUnsafe(config.maxIdleTime) : DEFAULT_MAX_IDLE_TIME,
110
107
  maxTransactionHistory: (_config$maxTransactio = config.maxTransactionHistory) !== null && _config$maxTransactio !== void 0 ? _config$maxTransactio : DEFAULT_MAX_TRANSACTION_HISTORY,
111
108
  snapshot: {
112
- interval: ((_config$snapshot = config.snapshot) === null || _config$snapshot === void 0 ? void 0 : _config$snapshot.interval) ? effect.Duration.decode(config.snapshot.interval) : DEFAULT_SNAPSHOT_INTERVAL,
109
+ interval: ((_config$snapshot = config.snapshot) === null || _config$snapshot === void 0 ? void 0 : _config$snapshot.interval) ? effect.Duration.fromInputUnsafe(config.snapshot.interval) : DEFAULT_SNAPSHOT_INTERVAL,
113
110
  transactionThreshold: (_config$snapshot$tran = (_config$snapshot2 = config.snapshot) === null || _config$snapshot2 === void 0 ? void 0 : _config$snapshot2.transactionThreshold) !== null && _config$snapshot$tran !== void 0 ? _config$snapshot$tran : DEFAULT_SNAPSHOT_THRESHOLD,
114
- idleTimeout: ((_config$snapshot3 = config.snapshot) === null || _config$snapshot3 === void 0 ? void 0 : _config$snapshot3.idleTimeout) ? effect.Duration.decode(config.snapshot.idleTimeout) : DEFAULT_SNAPSHOT_IDLE_TIMEOUT
111
+ idleTimeout: ((_config$snapshot3 = config.snapshot) === null || _config$snapshot3 === void 0 ? void 0 : _config$snapshot3.idleTimeout) ? effect.Duration.fromInputUnsafe(config.snapshot.idleTimeout) : DEFAULT_SNAPSHOT_IDLE_TIMEOUT
115
112
  },
116
113
  shardGroup: (_config$shardGroup = config.shardGroup) !== null && _config$shardGroup !== void 0 ? _config$shardGroup : DEFAULT_SHARD_GROUP
117
114
  };
@@ -134,7 +131,7 @@ const encodeTransaction = (tx) => {
134
131
  * Create the entity handler for MimicDocument
135
132
  */
136
133
  const createEntityHandler = (config, coldStorage, hotStorage) => effect.Effect.fn("cluster.entity.handler.create")(function* () {
137
- const documentId = (yield* _effect_cluster.Entity.CurrentAddress).entityId;
134
+ const documentId = (yield* effect_unstable_cluster.Entity.CurrentAddress).entityId;
138
135
  const instance = yield* require_DocumentInstance.DocumentInstance.make(documentId, {
139
136
  schema: config.schema,
140
137
  initial: config.initial,
@@ -148,27 +145,27 @@ const createEntityHandler = (config, coldStorage, hotStorage) => effect.Effect.f
148
145
  presencePubSub
149
146
  });
150
147
  yield* effect.Effect.addFinalizer(() => effect.Effect.fn("cluster.entity.finalize")(function* () {
151
- yield* effect.Effect.catchAll(instance.saveSnapshot(), (e) => effect.Effect.logError("Failed to save snapshot during entity finalization", {
148
+ yield* effect.Effect["catch"](instance.saveSnapshot(), (e) => effect.Effect.logError("Failed to save snapshot during entity finalization", {
152
149
  documentId,
153
150
  error: e
154
151
  }));
155
- yield* effect.Metric.incrementBy(require_Metrics.documentsActive, -1);
156
- yield* effect.Metric.increment(require_Metrics.documentsEvicted);
152
+ yield* effect.Metric.update(require_Metrics.documentsActive, -1);
153
+ yield* effect.Metric.update(require_Metrics.documentsEvicted, 1);
157
154
  yield* effect.Effect.logDebug("Entity finalized", { documentId });
158
155
  })());
159
156
  if (effect.Duration.toMillis(config.snapshot.idleTimeout) > 0) yield* effect.Effect.fn("cluster.entity.snapshot.loop")(function* () {
160
157
  if (yield* instance.needsSnapshot()) {
161
- yield* effect.Effect.catchAll(instance.saveSnapshot(), (e) => effect.Effect.logWarning("Periodic snapshot failed in cluster entity", {
158
+ yield* effect.Effect["catch"](instance.saveSnapshot(), (e) => effect.Effect.logWarning("Periodic snapshot failed in cluster entity", {
162
159
  documentId,
163
160
  error: e
164
161
  }));
165
- yield* effect.Metric.increment(require_Metrics.storageIdleSnapshots);
162
+ yield* effect.Metric.update(require_Metrics.storageIdleSnapshots, 1);
166
163
  }
167
- })().pipe(effect.Effect.repeat(effect.Schedule.spaced(config.snapshot.idleTimeout)), effect.Effect.fork);
164
+ })().pipe(effect.Effect.repeat(effect.Schedule.spaced(config.snapshot.idleTimeout)), effect.Effect.forkChild);
168
165
  return {
169
166
  Submit: effect.Effect.fn("cluster.document.transaction.submit")(function* ({ payload }) {
170
167
  const transaction = decodeTransaction(payload.transaction);
171
- return yield* instance.submit(transaction).pipe(effect.Effect.catchAll((error) => effect.Effect.succeed({
168
+ return yield* instance.submit(transaction).pipe(effect.Effect["catch"]((error) => effect.Effect.succeed({
172
169
  success: false,
173
170
  reason: `Storage error: ${String(error)}`
174
171
  })));
@@ -185,8 +182,8 @@ const createEntityHandler = (config, coldStorage, hotStorage) => effect.Effect.f
185
182
  SetPresence: effect.Effect.fn("cluster.presence.set")(function* ({ payload }) {
186
183
  const { connectionId, entry } = payload;
187
184
  yield* effect.Ref.update(stateRef, (s) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, s), {}, { presences: effect.HashMap.set(s.presences, connectionId, entry) }));
188
- yield* effect.Metric.increment(require_Metrics.presenceUpdates);
189
- yield* effect.Metric.incrementBy(require_Metrics.presenceActive, 1);
185
+ yield* effect.Metric.update(require_Metrics.presenceUpdates, 1);
186
+ yield* effect.Metric.update(require_Metrics.presenceActive, 1);
190
187
  const state = yield* effect.Ref.get(stateRef);
191
188
  const event = {
192
189
  type: "presence_update",
@@ -201,7 +198,7 @@ const createEntityHandler = (config, coldStorage, hotStorage) => effect.Effect.f
201
198
  const state = yield* effect.Ref.get(stateRef);
202
199
  if (!effect.HashMap.has(state.presences, connectionId)) return;
203
200
  yield* effect.Ref.update(stateRef, (s) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, s), {}, { presences: effect.HashMap.remove(s.presences, connectionId) }));
204
- yield* effect.Metric.incrementBy(require_Metrics.presenceActive, -1);
201
+ yield* effect.Metric.update(require_Metrics.presenceActive, -1);
205
202
  const event = {
206
203
  type: "presence_remove",
207
204
  id: connectionId
@@ -216,7 +213,7 @@ const createEntityHandler = (config, coldStorage, hotStorage) => effect.Effect.f
216
213
  })
217
214
  };
218
215
  })();
219
- var SubscriptionStoreTag = class extends effect.Context.Tag("@voidhash/mimic-effect/SubscriptionStore")() {};
216
+ var SubscriptionStoreTag = class extends effect.ServiceMap.Service()("@voidhash/mimic-effect/SubscriptionStore") {};
220
217
  const subscriptionStoreLayer = effect.Layer.effect(SubscriptionStoreTag, effect.Effect.fn("cluster.subscriptions.layer.create")(function* () {
221
218
  const documentPubSubs = yield* effect.Ref.make(effect.HashMap.empty());
222
219
  const presencePubSubs = yield* effect.Ref.make(effect.HashMap.empty());
@@ -282,14 +279,14 @@ const make = (config) => {
282
279
  concurrency: 1,
283
280
  mailboxCapacity: 4096
284
281
  });
285
- const engineLayer = effect.Layer.scoped(require_MimicServerEngine.MimicServerEngineTag, effect.Effect.gen(function* () {
282
+ const engineLayer = effect.Layer.effect(require_MimicServerEngine.MimicServerEngineTag, effect.Effect.gen(function* () {
286
283
  const makeClient = yield* MimicDocumentEntity.client;
287
284
  const subscriptionStore = yield* SubscriptionStoreTag;
288
285
  return {
289
286
  submit: (documentId, transaction) => effect.Effect.gen(function* () {
290
287
  const client = makeClient(documentId);
291
288
  const encodedTx = encodeTransaction(transaction);
292
- const result = yield* client.Submit({ transaction: encodedTx }).pipe(effect.Effect.catchAll((error) => effect.Effect.succeed({
289
+ const result = yield* client.Submit({ transaction: encodedTx }).pipe(effect.Effect["catch"]((error) => effect.Effect.succeed({
293
290
  success: false,
294
291
  reason: `Cluster error: ${String(error)}`
295
292
  })));
@@ -5,7 +5,7 @@ import { MimicAuthServiceTag } from "./MimicAuthService.cjs";
5
5
  import { MimicServerEngineTag } from "./MimicServerEngine.cjs";
6
6
  import { Layer } from "effect";
7
7
  import { Primitive } from "@voidhash/mimic";
8
- import { Sharding } from "@effect/cluster";
8
+ import { Sharding } from "effect/unstable/cluster";
9
9
 
10
10
  //#region src/MimicClusterServerEngine.d.ts
11
11
 
@@ -5,7 +5,7 @@ import { MimicAuthServiceTag } from "./MimicAuthService.mjs";
5
5
  import { MimicServerEngineTag } from "./MimicServerEngine.mjs";
6
6
  import { Layer } from "effect";
7
7
  import { Primitive } from "@voidhash/mimic";
8
- import { Sharding } from "@effect/cluster";
8
+ import { Sharding } from "effect/unstable/cluster";
9
9
 
10
10
  //#region src/MimicClusterServerEngine.d.ts
11
11
 
@@ -5,9 +5,9 @@ import { documentsActive, documentsEvicted, presenceActive, presenceUpdates, sto
5
5
  import { DocumentInstance } from "./DocumentInstance.mjs";
6
6
  import { _objectSpread2 } from "./_virtual/_@oxc-project_runtime@0.103.0/helpers/objectSpread2.mjs";
7
7
  import { MimicServerEngineTag } from "./MimicServerEngine.mjs";
8
- import { Context, Duration, Effect, HashMap, Layer, Metric, PubSub, Ref, Schedule, Schema, Stream } from "effect";
9
- import { Entity } from "@effect/cluster";
10
- import { Rpc } from "@effect/rpc";
8
+ import { Duration, Effect, HashMap, Layer, Metric, PubSub, Ref, Schedule, Schema, ServiceMap, Stream } from "effect";
9
+ import { Entity } from "effect/unstable/cluster";
10
+ import { Rpc } from "effect/unstable/rpc";
11
11
 
12
12
  //#region src/MimicClusterServerEngine.ts
13
13
  /**
@@ -29,49 +29,46 @@ const DEFAULT_SHARD_GROUP = "mimic-documents";
29
29
  */
30
30
  const EncodedTransactionSchema = Schema.Struct({
31
31
  id: Schema.String,
32
- ops: Schema.Array(Schema.Unknown)
32
+ ops: Schema.Array(Schema.Any)
33
33
  });
34
34
  /**
35
35
  * Schema for submit result
36
36
  */
37
- const SubmitResultSchema = Schema.Union(Schema.Struct({
37
+ const SubmitResultSchema = Schema.Union([Schema.Struct({
38
38
  success: Schema.Literal(true),
39
39
  version: Schema.Number
40
40
  }), Schema.Struct({
41
41
  success: Schema.Literal(false),
42
42
  reason: Schema.String
43
- }));
43
+ })]);
44
44
  /**
45
45
  * Schema for snapshot response
46
46
  */
47
47
  const SnapshotResponseSchema = Schema.Struct({
48
- state: Schema.Unknown,
48
+ state: Schema.Any,
49
49
  version: Schema.Number
50
50
  });
51
51
  /**
52
52
  * Schema for presence entry
53
53
  */
54
54
  const PresenceEntrySchema = Schema.Struct({
55
- data: Schema.Unknown,
55
+ data: Schema.Any,
56
56
  userId: Schema.optional(Schema.String)
57
57
  });
58
58
  /**
59
59
  * Schema for presence snapshot response
60
60
  */
61
- const PresenceSnapshotResponseSchema = Schema.Struct({ presences: Schema.Record({
62
- key: Schema.String,
63
- value: PresenceEntrySchema
64
- }) });
65
- Schema.Union(Schema.Struct({
61
+ const PresenceSnapshotResponseSchema = Schema.Struct({ presences: Schema.Record(Schema.String, PresenceEntrySchema) });
62
+ Schema.Union([Schema.Struct({
66
63
  type: Schema.Literal("presence_update"),
67
64
  id: Schema.String,
68
- data: Schema.Unknown,
65
+ data: Schema.Any,
69
66
  userId: Schema.optional(Schema.String)
70
67
  }), Schema.Struct({
71
68
  type: Schema.Literal("presence_remove"),
72
69
  id: Schema.String
73
- }));
74
- Schema.Unknown;
70
+ })]);
71
+ Schema.Any;
75
72
  /**
76
73
  * Define the Mimic Document Entity with its RPC protocol.
77
74
  * This entity handles document operations for a single documentId.
@@ -82,7 +79,7 @@ const MimicDocumentEntity = Entity.make("MimicDocument", [
82
79
  success: SubmitResultSchema
83
80
  }),
84
81
  Rpc.make("GetSnapshot", { success: SnapshotResponseSchema }),
85
- Rpc.make("GetTreeSnapshot", { success: Schema.Unknown }),
82
+ Rpc.make("GetTreeSnapshot", { success: Schema.Any }),
86
83
  Rpc.make("Touch", { success: Schema.Void }),
87
84
  Rpc.make("SetPresence", {
88
85
  payload: {
@@ -100,19 +97,19 @@ const MimicDocumentEntity = Entity.make("MimicDocument", [
100
97
  /**
101
98
  * Context tag for cluster engine configuration
102
99
  */
103
- var MimicClusterConfigTag = class extends Context.Tag("@voidhash/mimic-effect/MimicClusterConfig")() {};
100
+ var MimicClusterConfigTag = class extends ServiceMap.Service()("@voidhash/mimic-effect/MimicClusterConfig") {};
104
101
  const resolveClusterConfig = (config) => {
105
102
  var _config$maxTransactio, _config$snapshot, _config$snapshot$tran, _config$snapshot2, _config$snapshot3, _config$shardGroup;
106
103
  return {
107
104
  schema: config.schema,
108
105
  initial: config.initial,
109
106
  presence: config.presence,
110
- maxIdleTime: config.maxIdleTime ? Duration.decode(config.maxIdleTime) : DEFAULT_MAX_IDLE_TIME,
107
+ maxIdleTime: config.maxIdleTime ? Duration.fromInputUnsafe(config.maxIdleTime) : DEFAULT_MAX_IDLE_TIME,
111
108
  maxTransactionHistory: (_config$maxTransactio = config.maxTransactionHistory) !== null && _config$maxTransactio !== void 0 ? _config$maxTransactio : DEFAULT_MAX_TRANSACTION_HISTORY,
112
109
  snapshot: {
113
- interval: ((_config$snapshot = config.snapshot) === null || _config$snapshot === void 0 ? void 0 : _config$snapshot.interval) ? Duration.decode(config.snapshot.interval) : DEFAULT_SNAPSHOT_INTERVAL,
110
+ interval: ((_config$snapshot = config.snapshot) === null || _config$snapshot === void 0 ? void 0 : _config$snapshot.interval) ? Duration.fromInputUnsafe(config.snapshot.interval) : DEFAULT_SNAPSHOT_INTERVAL,
114
111
  transactionThreshold: (_config$snapshot$tran = (_config$snapshot2 = config.snapshot) === null || _config$snapshot2 === void 0 ? void 0 : _config$snapshot2.transactionThreshold) !== null && _config$snapshot$tran !== void 0 ? _config$snapshot$tran : DEFAULT_SNAPSHOT_THRESHOLD,
115
- idleTimeout: ((_config$snapshot3 = config.snapshot) === null || _config$snapshot3 === void 0 ? void 0 : _config$snapshot3.idleTimeout) ? Duration.decode(config.snapshot.idleTimeout) : DEFAULT_SNAPSHOT_IDLE_TIMEOUT
112
+ idleTimeout: ((_config$snapshot3 = config.snapshot) === null || _config$snapshot3 === void 0 ? void 0 : _config$snapshot3.idleTimeout) ? Duration.fromInputUnsafe(config.snapshot.idleTimeout) : DEFAULT_SNAPSHOT_IDLE_TIMEOUT
116
113
  },
117
114
  shardGroup: (_config$shardGroup = config.shardGroup) !== null && _config$shardGroup !== void 0 ? _config$shardGroup : DEFAULT_SHARD_GROUP
118
115
  };
@@ -149,27 +146,27 @@ const createEntityHandler = (config, coldStorage, hotStorage) => Effect.fn("clus
149
146
  presencePubSub
150
147
  });
151
148
  yield* Effect.addFinalizer(() => Effect.fn("cluster.entity.finalize")(function* () {
152
- yield* Effect.catchAll(instance.saveSnapshot(), (e) => Effect.logError("Failed to save snapshot during entity finalization", {
149
+ yield* Effect["catch"](instance.saveSnapshot(), (e) => Effect.logError("Failed to save snapshot during entity finalization", {
153
150
  documentId,
154
151
  error: e
155
152
  }));
156
- yield* Metric.incrementBy(documentsActive, -1);
157
- yield* Metric.increment(documentsEvicted);
153
+ yield* Metric.update(documentsActive, -1);
154
+ yield* Metric.update(documentsEvicted, 1);
158
155
  yield* Effect.logDebug("Entity finalized", { documentId });
159
156
  })());
160
157
  if (Duration.toMillis(config.snapshot.idleTimeout) > 0) yield* Effect.fn("cluster.entity.snapshot.loop")(function* () {
161
158
  if (yield* instance.needsSnapshot()) {
162
- yield* Effect.catchAll(instance.saveSnapshot(), (e) => Effect.logWarning("Periodic snapshot failed in cluster entity", {
159
+ yield* Effect["catch"](instance.saveSnapshot(), (e) => Effect.logWarning("Periodic snapshot failed in cluster entity", {
163
160
  documentId,
164
161
  error: e
165
162
  }));
166
- yield* Metric.increment(storageIdleSnapshots);
163
+ yield* Metric.update(storageIdleSnapshots, 1);
167
164
  }
168
- })().pipe(Effect.repeat(Schedule.spaced(config.snapshot.idleTimeout)), Effect.fork);
165
+ })().pipe(Effect.repeat(Schedule.spaced(config.snapshot.idleTimeout)), Effect.forkChild);
169
166
  return {
170
167
  Submit: Effect.fn("cluster.document.transaction.submit")(function* ({ payload }) {
171
168
  const transaction = decodeTransaction(payload.transaction);
172
- return yield* instance.submit(transaction).pipe(Effect.catchAll((error) => Effect.succeed({
169
+ return yield* instance.submit(transaction).pipe(Effect["catch"]((error) => Effect.succeed({
173
170
  success: false,
174
171
  reason: `Storage error: ${String(error)}`
175
172
  })));
@@ -186,8 +183,8 @@ const createEntityHandler = (config, coldStorage, hotStorage) => Effect.fn("clus
186
183
  SetPresence: Effect.fn("cluster.presence.set")(function* ({ payload }) {
187
184
  const { connectionId, entry } = payload;
188
185
  yield* Ref.update(stateRef, (s) => _objectSpread2(_objectSpread2({}, s), {}, { presences: HashMap.set(s.presences, connectionId, entry) }));
189
- yield* Metric.increment(presenceUpdates);
190
- yield* Metric.incrementBy(presenceActive, 1);
186
+ yield* Metric.update(presenceUpdates, 1);
187
+ yield* Metric.update(presenceActive, 1);
191
188
  const state = yield* Ref.get(stateRef);
192
189
  const event = {
193
190
  type: "presence_update",
@@ -202,7 +199,7 @@ const createEntityHandler = (config, coldStorage, hotStorage) => Effect.fn("clus
202
199
  const state = yield* Ref.get(stateRef);
203
200
  if (!HashMap.has(state.presences, connectionId)) return;
204
201
  yield* Ref.update(stateRef, (s) => _objectSpread2(_objectSpread2({}, s), {}, { presences: HashMap.remove(s.presences, connectionId) }));
205
- yield* Metric.incrementBy(presenceActive, -1);
202
+ yield* Metric.update(presenceActive, -1);
206
203
  const event = {
207
204
  type: "presence_remove",
208
205
  id: connectionId
@@ -217,7 +214,7 @@ const createEntityHandler = (config, coldStorage, hotStorage) => Effect.fn("clus
217
214
  })
218
215
  };
219
216
  })();
220
- var SubscriptionStoreTag = class extends Context.Tag("@voidhash/mimic-effect/SubscriptionStore")() {};
217
+ var SubscriptionStoreTag = class extends ServiceMap.Service()("@voidhash/mimic-effect/SubscriptionStore") {};
221
218
  const subscriptionStoreLayer = Layer.effect(SubscriptionStoreTag, Effect.fn("cluster.subscriptions.layer.create")(function* () {
222
219
  const documentPubSubs = yield* Ref.make(HashMap.empty());
223
220
  const presencePubSubs = yield* Ref.make(HashMap.empty());
@@ -283,14 +280,14 @@ const make = (config) => {
283
280
  concurrency: 1,
284
281
  mailboxCapacity: 4096
285
282
  });
286
- const engineLayer = Layer.scoped(MimicServerEngineTag, Effect.gen(function* () {
283
+ const engineLayer = Layer.effect(MimicServerEngineTag, Effect.gen(function* () {
287
284
  const makeClient = yield* MimicDocumentEntity.client;
288
285
  const subscriptionStore = yield* SubscriptionStoreTag;
289
286
  return {
290
287
  submit: (documentId, transaction) => Effect.gen(function* () {
291
288
  const client = makeClient(documentId);
292
289
  const encodedTx = encodeTransaction(transaction);
293
- const result = yield* client.Submit({ transaction: encodedTx }).pipe(Effect.catchAll((error) => Effect.succeed({
290
+ const result = yield* client.Submit({ transaction: encodedTx }).pipe(Effect["catch"]((error) => Effect.succeed({
294
291
  success: false,
295
292
  reason: `Cluster error: ${String(error)}`
296
293
  })));
@@ -1 +1 @@
1
- {"version":3,"file":"MimicClusterServerEngine.mjs","names":["Metrics.documentsActive","Metrics.documentsEvicted","Metrics.storageIdleSnapshots","Metrics.presenceUpdates","Metrics.presenceActive","event: PresenceEvent","presences: Record<string, PresenceEntry>"],"sources":["../src/MimicClusterServerEngine.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect - MimicClusterServerEngine\n *\n * Clustered document management service using Effect Cluster for horizontal scaling.\n * Each document becomes a cluster Entity with automatic sharding, failover, and location-transparent routing.\n *\n * This is an alternative to MimicServerEngine for distributed deployments.\n */\nimport {\n Context,\n Duration,\n Effect,\n HashMap,\n Layer,\n Metric,\n PubSub,\n Ref,\n Schedule,\n Schema,\n Stream,\n} from \"effect\";\nimport { Entity, Sharding } from \"@effect/cluster\";\nimport { Rpc } from \"@effect/rpc\";\nimport { type Primitive, type Transaction } from \"@voidhash/mimic\";\nimport type {\n MimicClusterServerEngineConfig,\n PresenceEntry,\n PresenceEvent,\n ResolvedClusterConfig,\n} from \"./Types\";\nimport type * as Protocol from \"./Protocol\";\nimport { ColdStorageTag, type ColdStorage } from \"./ColdStorage\";\nimport { HotStorageTag, type HotStorage } from \"./HotStorage\";\nimport { MimicAuthServiceTag } from \"./MimicAuthService\";\nimport { MimicServerEngineTag, type MimicServerEngine } from \"./MimicServerEngine\";\nimport {\n DocumentInstance,\n type DocumentInstance as DocumentInstanceInterface,\n} from \"./DocumentInstance\";\nimport * as Metrics from \"./Metrics\";\n\n// =============================================================================\n// Default Configuration\n// =============================================================================\n\nconst DEFAULT_MAX_IDLE_TIME = Duration.minutes(5);\nconst DEFAULT_MAX_TRANSACTION_HISTORY = 1000;\nconst DEFAULT_SNAPSHOT_INTERVAL = Duration.minutes(5);\nconst DEFAULT_SNAPSHOT_THRESHOLD = 100;\nconst DEFAULT_SNAPSHOT_IDLE_TIMEOUT = Duration.seconds(30);\nconst DEFAULT_SHARD_GROUP = \"mimic-documents\";\n\n// =============================================================================\n// RPC Schemas\n// =============================================================================\n\n/**\n * Schema for encoded transaction (wire format)\n */\nconst EncodedTransactionSchema = Schema.Struct({\n id: Schema.String,\n ops: Schema.Array(Schema.Unknown),\n});\n\n/**\n * Schema for submit result\n */\nconst SubmitResultSchema = Schema.Union(\n Schema.Struct({\n success: Schema.Literal(true),\n version: Schema.Number,\n }),\n Schema.Struct({\n success: Schema.Literal(false),\n reason: Schema.String,\n })\n);\n\n/**\n * Schema for snapshot response\n */\nconst SnapshotResponseSchema = Schema.Struct({\n state: Schema.Unknown,\n version: Schema.Number,\n});\n\n/**\n * Schema for presence entry\n */\nconst PresenceEntrySchema = Schema.Struct({\n data: Schema.Unknown,\n userId: Schema.optional(Schema.String),\n});\n\n/**\n * Schema for presence snapshot response\n */\nconst PresenceSnapshotResponseSchema = Schema.Struct({\n presences: Schema.Record({ key: Schema.String, value: PresenceEntrySchema }),\n});\n\n/**\n * Schema for presence event\n */\nconst PresenceEventSchema = Schema.Union(\n Schema.Struct({\n type: Schema.Literal(\"presence_update\"),\n id: Schema.String,\n data: Schema.Unknown,\n userId: Schema.optional(Schema.String),\n }),\n Schema.Struct({\n type: Schema.Literal(\"presence_remove\"),\n id: Schema.String,\n })\n);\n\n/**\n * Schema for server message (for broadcasts)\n */\nconst ServerMessageSchema = Schema.Unknown;\n\n// =============================================================================\n// Mimic Document Entity Definition\n// =============================================================================\n\n/**\n * Define the Mimic Document Entity with its RPC protocol.\n * This entity handles document operations for a single documentId.\n */\nconst MimicDocumentEntity = Entity.make(\"MimicDocument\", [\n // Submit a transaction\n Rpc.make(\"Submit\", {\n payload: { transaction: EncodedTransactionSchema },\n success: SubmitResultSchema,\n }),\n\n // Get document snapshot (flat state)\n Rpc.make(\"GetSnapshot\", {\n success: SnapshotResponseSchema,\n }),\n\n // Get tree-like snapshot for rendering\n Rpc.make(\"GetTreeSnapshot\", {\n success: Schema.Unknown,\n }),\n\n // Touch document to prevent idle GC\n Rpc.make(\"Touch\", {\n success: Schema.Void,\n }),\n\n // Set presence for a connection\n Rpc.make(\"SetPresence\", {\n payload: {\n connectionId: Schema.String,\n entry: PresenceEntrySchema,\n },\n success: Schema.Void,\n }),\n\n // Remove presence for a connection\n Rpc.make(\"RemovePresence\", {\n payload: { connectionId: Schema.String },\n success: Schema.Void,\n }),\n\n // Get presence snapshot\n Rpc.make(\"GetPresenceSnapshot\", {\n success: PresenceSnapshotResponseSchema,\n }),\n]);\n\n// =============================================================================\n// Entity State Types\n// =============================================================================\n\n/**\n * Entity state that wraps DocumentInstance and adds presence management\n */\ninterface EntityState<TSchema extends Primitive.AnyPrimitive> {\n readonly instance: DocumentInstanceInterface<TSchema>;\n readonly presences: HashMap.HashMap<string, PresenceEntry>;\n readonly presencePubSub: PubSub.PubSub<PresenceEvent>;\n}\n\n// =============================================================================\n// Config Context Tag\n// =============================================================================\n\n/**\n * Context tag for cluster engine configuration\n */\nclass MimicClusterConfigTag extends Context.Tag(\n \"@voidhash/mimic-effect/MimicClusterConfig\"\n)<MimicClusterConfigTag, ResolvedClusterConfig<Primitive.AnyPrimitive>>() {}\n\n// =============================================================================\n// Resolve Configuration\n// =============================================================================\n\nconst resolveClusterConfig = <TSchema extends Primitive.AnyPrimitive>(\n config: MimicClusterServerEngineConfig<TSchema>\n): ResolvedClusterConfig<TSchema> => ({\n schema: config.schema,\n initial: config.initial,\n presence: config.presence,\n maxIdleTime: config.maxIdleTime\n ? Duration.decode(config.maxIdleTime)\n : DEFAULT_MAX_IDLE_TIME,\n maxTransactionHistory:\n config.maxTransactionHistory ?? DEFAULT_MAX_TRANSACTION_HISTORY,\n snapshot: {\n interval: config.snapshot?.interval\n ? Duration.decode(config.snapshot.interval)\n : DEFAULT_SNAPSHOT_INTERVAL,\n transactionThreshold:\n config.snapshot?.transactionThreshold ?? DEFAULT_SNAPSHOT_THRESHOLD,\n idleTimeout: config.snapshot?.idleTimeout\n ? Duration.decode(config.snapshot.idleTimeout)\n : DEFAULT_SNAPSHOT_IDLE_TIMEOUT,\n },\n shardGroup: config.shardGroup ?? DEFAULT_SHARD_GROUP,\n});\n\n// =============================================================================\n// Helper to decode/encode transactions\n// =============================================================================\n\n/**\n * Decode an encoded transaction to a Transaction object\n */\nconst decodeTransaction = (\n encoded: { id: string; ops: readonly unknown[] }\n): Transaction.Transaction => {\n // Import Transaction dynamically to avoid circular deps\n const { Transaction } = require(\"@voidhash/mimic\");\n return Transaction.decode(encoded as Transaction.EncodedTransaction);\n};\n\n/**\n * Encode a Transaction to wire format\n */\nconst encodeTransaction = (\n tx: Transaction.Transaction\n): { id: string; ops: readonly unknown[] } => {\n const { Transaction } = require(\"@voidhash/mimic\");\n return Transaction.encode(tx);\n};\n\n// =============================================================================\n// Entity Handler Factory\n// =============================================================================\n\n/**\n * Create the entity handler for MimicDocument\n */\nconst createEntityHandler = <TSchema extends Primitive.AnyPrimitive>(\n config: ResolvedClusterConfig<TSchema>,\n coldStorage: ColdStorage,\n hotStorage: HotStorage\n) =>\n Effect.fn(\"cluster.entity.handler.create\")(function* () {\n // Get entity address to determine documentId\n const address = yield* Entity.CurrentAddress;\n const documentId = address.entityId;\n\n // Create DocumentInstance (fatal if unavailable - entity cannot start)\n const instance = yield* DocumentInstance.make(\n documentId,\n {\n schema: config.schema,\n initial: config.initial,\n maxTransactionHistory: config.maxTransactionHistory,\n snapshot: config.snapshot,\n },\n coldStorage,\n hotStorage\n ).pipe(Effect.orDie);\n\n // Create presence PubSub and state ref\n const presencePubSub = yield* PubSub.unbounded<PresenceEvent>();\n const stateRef = yield* Ref.make<EntityState<TSchema>>({\n instance,\n presences: HashMap.empty(),\n presencePubSub,\n });\n\n // Cleanup on entity finalization\n yield* Effect.addFinalizer(() =>\n Effect.fn(\"cluster.entity.finalize\")(function* () {\n // Best effort save - don't fail shutdown if storage is unavailable\n yield* Effect.catchAll(instance.saveSnapshot(), (e) =>\n Effect.logError(\"Failed to save snapshot during entity finalization\", {\n documentId,\n error: e,\n })\n );\n yield* Metric.incrementBy(Metrics.documentsActive, -1);\n yield* Metric.increment(Metrics.documentsEvicted);\n yield* Effect.logDebug(\"Entity finalized\", { documentId });\n })()\n );\n\n // Start periodic snapshot fiber for this entity\n const idleTimeoutMs = Duration.toMillis(config.snapshot.idleTimeout);\n if (idleTimeoutMs > 0) {\n const snapshotLoop = Effect.fn(\"cluster.entity.snapshot.loop\")(function* () {\n const needs = yield* instance.needsSnapshot();\n if (needs) {\n yield* Effect.catchAll(instance.saveSnapshot(), (e) =>\n Effect.logWarning(\"Periodic snapshot failed in cluster entity\", {\n documentId,\n error: e,\n })\n );\n yield* Metric.increment(Metrics.storageIdleSnapshots);\n }\n });\n\n // Run every idleTimeout\n yield* snapshotLoop().pipe(\n Effect.repeat(Schedule.spaced(config.snapshot.idleTimeout)),\n Effect.fork\n );\n }\n\n // Return RPC handlers\n return {\n Submit: Effect.fn(\"cluster.document.transaction.submit\")(function* ({\n payload,\n }) {\n // Decode transaction\n const transaction = decodeTransaction(payload.transaction);\n\n // Use DocumentInstance's submit method, catching storage errors\n return yield* instance.submit(transaction).pipe(\n Effect.catchAll((error) =>\n Effect.succeed({\n success: false as const,\n reason: `Storage error: ${String(error)}`,\n })\n )\n );\n }),\n\n GetSnapshot: Effect.fn(\"cluster.document.snapshot.get\")(function* () {\n return instance.getSnapshot();\n }),\n\n GetTreeSnapshot: Effect.fn(\"cluster.document.tree-snapshot.get\")(function* () {\n return instance.toSnapshot();\n }),\n\n Touch: Effect.fn(\"cluster.document.touch\")(function* () {\n yield* instance.touch();\n }),\n\n SetPresence: Effect.fn(\"cluster.presence.set\")(function* ({ payload }) {\n const { connectionId, entry } = payload;\n\n yield* Ref.update(stateRef, (s) => ({\n ...s,\n presences: HashMap.set(s.presences, connectionId, entry),\n }));\n\n yield* Metric.increment(Metrics.presenceUpdates);\n yield* Metric.incrementBy(Metrics.presenceActive, 1);\n\n const state = yield* Ref.get(stateRef);\n const event: PresenceEvent = {\n type: \"presence_update\",\n id: connectionId,\n data: entry.data,\n userId: entry.userId,\n };\n yield* PubSub.publish(state.presencePubSub, event);\n }),\n\n RemovePresence: Effect.fn(\"cluster.presence.remove\")(function* ({\n payload,\n }) {\n const { connectionId } = payload;\n const state = yield* Ref.get(stateRef);\n\n if (!HashMap.has(state.presences, connectionId)) {\n return;\n }\n\n yield* Ref.update(stateRef, (s) => ({\n ...s,\n presences: HashMap.remove(s.presences, connectionId),\n }));\n\n yield* Metric.incrementBy(Metrics.presenceActive, -1);\n\n const event: PresenceEvent = {\n type: \"presence_remove\",\n id: connectionId,\n };\n yield* PubSub.publish(state.presencePubSub, event);\n }),\n\n GetPresenceSnapshot: Effect.fn(\"cluster.presence.snapshot.get\")(\n function* () {\n const state = yield* Ref.get(stateRef);\n const presences: Record<string, PresenceEntry> = {};\n for (const [id, entry] of state.presences) {\n presences[id] = entry;\n }\n return { presences };\n }\n ),\n };\n })();\n\n// =============================================================================\n// Subscription Store (for managing subscriptions at the gateway level)\n// =============================================================================\n\n/**\n * Store for managing document subscriptions\n * This is needed because cluster entities don't support streaming directly\n */\ninterface SubscriptionStore {\n readonly getOrCreatePubSub: (\n documentId: string\n ) => Effect.Effect<PubSub.PubSub<Protocol.ServerMessage>>;\n readonly getOrCreatePresencePubSub: (\n documentId: string\n ) => Effect.Effect<PubSub.PubSub<PresenceEvent>>;\n}\n\nclass SubscriptionStoreTag extends Context.Tag(\n \"@voidhash/mimic-effect/SubscriptionStore\"\n)<SubscriptionStoreTag, SubscriptionStore>() {}\n\nconst subscriptionStoreLayer = Layer.effect(\n SubscriptionStoreTag,\n Effect.fn(\"cluster.subscriptions.layer.create\")(function* () {\n const documentPubSubs = yield* Ref.make(\n HashMap.empty<string, PubSub.PubSub<Protocol.ServerMessage>>()\n );\n const presencePubSubs = yield* Ref.make(\n HashMap.empty<string, PubSub.PubSub<PresenceEvent>>()\n );\n\n return {\n getOrCreatePubSub: Effect.fn(\n \"cluster.subscriptions.pubsub.get-or-create\"\n )(function* (documentId: string) {\n const current = yield* Ref.get(documentPubSubs);\n const existing = HashMap.get(current, documentId);\n if (existing._tag === \"Some\") {\n return existing.value;\n }\n\n const pubsub = yield* PubSub.unbounded<Protocol.ServerMessage>();\n yield* Ref.update(documentPubSubs, (map) =>\n HashMap.set(map, documentId, pubsub)\n );\n return pubsub;\n }),\n\n getOrCreatePresencePubSub: Effect.fn(\n \"cluster.subscriptions.presence-pubsub.get-or-create\"\n )(function* (documentId: string) {\n const current = yield* Ref.get(presencePubSubs);\n const existing = HashMap.get(current, documentId);\n if (existing._tag === \"Some\") {\n return existing.value;\n }\n\n const pubsub = yield* PubSub.unbounded<PresenceEvent>();\n yield* Ref.update(presencePubSubs, (map) =>\n HashMap.set(map, documentId, pubsub)\n );\n return pubsub;\n }),\n };\n })()\n);\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a MimicClusterServerEngine layer.\n *\n * This creates a clustered document management service using Effect Cluster.\n * Each document becomes a cluster Entity with automatic sharding and failover.\n *\n * @example\n * ```typescript\n * // 1. Create the engine\n * const Engine = MimicClusterServerEngine.make({\n * schema: DocSchema,\n * initial: { title: \"Untitled\" },\n * presence: CursorPresence,\n * maxIdleTime: \"5 minutes\",\n * snapshot: { interval: \"5 minutes\", transactionThreshold: 100 },\n * shardGroup: \"documents\",\n * })\n *\n * // 2. Create the WebSocket route\n * const MimicRoute = MimicServer.layerHttpLayerRouter({\n * path: \"/mimic\",\n * })\n *\n * // 3. Wire together with cluster infrastructure\n * const MimicLive = MimicRoute.pipe(\n * Layer.provide(Engine),\n * Layer.provide(ColdStorage.S3.make(...)),\n * Layer.provide(HotStorage.Redis.make(...)),\n * Layer.provide(MimicAuthService.make(...)),\n * Layer.provide(ClusterInfrastructure),\n * )\n * ```\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n config: MimicClusterServerEngineConfig<TSchema>\n): Layer.Layer<\n MimicServerEngineTag,\n never,\n ColdStorageTag | HotStorageTag | MimicAuthServiceTag | Sharding.Sharding\n> => {\n const resolvedConfig = resolveClusterConfig(config);\n\n // Create config layer\n const configLayer = Layer.succeed(\n MimicClusterConfigTag,\n resolvedConfig as ResolvedClusterConfig<Primitive.AnyPrimitive>\n );\n\n // Create entity layer that registers with sharding\n const entityLayer = MimicDocumentEntity.toLayer(\n Effect.gen(function* () {\n const clusterConfig = yield* MimicClusterConfigTag;\n const coldStorage = yield* ColdStorageTag;\n const hotStorage = yield* HotStorageTag;\n\n return yield* createEntityHandler(\n clusterConfig as ResolvedClusterConfig<TSchema>,\n coldStorage,\n hotStorage\n );\n }),\n {\n maxIdleTime: resolvedConfig.maxIdleTime,\n concurrency: 1, // Sequential message processing per document\n mailboxCapacity: 4096,\n }\n );\n\n // Create the engine service\n const engineLayer = Layer.scoped(\n MimicServerEngineTag,\n Effect.gen(function* () {\n // Get entity client maker\n const makeClient = yield* MimicDocumentEntity.client;\n\n // Get subscription store\n const subscriptionStore = yield* SubscriptionStoreTag;\n\n const engine: MimicServerEngine = {\n submit: (documentId, transaction) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n const encodedTx = encodeTransaction(transaction);\n const result = yield* client.Submit({\n transaction: encodedTx as { id: string; ops: unknown[] },\n }).pipe(\n Effect.catchAll((error) =>\n Effect.succeed({\n success: false as const,\n reason: `Cluster error: ${String(error)}`,\n })\n )\n );\n\n // Broadcast to local subscribers if success\n if (result.success) {\n const pubsub =\n yield* subscriptionStore.getOrCreatePubSub(documentId);\n yield* PubSub.publish(pubsub, {\n type: \"transaction\",\n transaction,\n version: result.version,\n } as Protocol.ServerMessage);\n }\n\n return result;\n }),\n\n getSnapshot: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n return yield* client.GetSnapshot(undefined as void).pipe(Effect.orDie);\n }),\n\n getTreeSnapshot: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n return yield* client.GetTreeSnapshot(undefined as void).pipe(Effect.orDie);\n }),\n\n subscribe: (documentId) =>\n Effect.gen(function* () {\n const pubsub =\n yield* subscriptionStore.getOrCreatePubSub(documentId);\n return Stream.fromPubSub(pubsub);\n }),\n\n touch: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n yield* client.Touch(undefined as void).pipe(Effect.orDie);\n }),\n\n getPresenceSnapshot: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n return yield* client.GetPresenceSnapshot(undefined as void).pipe(Effect.orDie);\n }),\n\n setPresence: (documentId, connectionId, entry) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n yield* client.SetPresence({ connectionId, entry }).pipe(Effect.orDie);\n\n // Broadcast to local presence subscribers\n const pubsub =\n yield* subscriptionStore.getOrCreatePresencePubSub(documentId);\n yield* PubSub.publish(pubsub, {\n type: \"presence_update\",\n id: connectionId,\n data: entry.data,\n userId: entry.userId,\n });\n }),\n\n removePresence: (documentId, connectionId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n yield* client.RemovePresence({ connectionId }).pipe(Effect.orDie);\n\n // Broadcast to local presence subscribers\n const pubsub =\n yield* subscriptionStore.getOrCreatePresencePubSub(documentId);\n yield* PubSub.publish(pubsub, {\n type: \"presence_remove\",\n id: connectionId,\n });\n }),\n\n subscribePresence: (documentId) =>\n Effect.gen(function* () {\n const pubsub =\n yield* subscriptionStore.getOrCreatePresencePubSub(documentId);\n return Stream.fromPubSub(pubsub);\n }),\n\n config: resolvedConfig as ResolvedClusterConfig<Primitive.AnyPrimitive>,\n };\n\n return engine;\n })\n );\n\n // Compose all layers\n return Layer.mergeAll(entityLayer, engineLayer).pipe(\n Layer.provideMerge(subscriptionStoreLayer),\n Layer.provideMerge(configLayer)\n );\n};\n\n// =============================================================================\n// Re-export namespace\n// =============================================================================\n\nexport const MimicClusterServerEngine = {\n make,\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"MimicClusterServerEngine.mjs","names":["Metrics.documentsActive","Metrics.documentsEvicted","Metrics.storageIdleSnapshots","Metrics.presenceUpdates","Metrics.presenceActive","event: PresenceEvent","presences: Record<string, PresenceEntry>"],"sources":["../src/MimicClusterServerEngine.ts"],"sourcesContent":["/**\n * @voidhash/mimic-effect - MimicClusterServerEngine\n *\n * Clustered document management service using Effect Cluster for horizontal scaling.\n * Each document becomes a cluster Entity with automatic sharding, failover, and location-transparent routing.\n *\n * This is an alternative to MimicServerEngine for distributed deployments.\n */\nimport {\n Duration,\n Effect,\n HashMap,\n Layer,\n Metric,\n PubSub,\n Ref,\n Schedule,\n Schema,\n ServiceMap,\n Stream,\n} from \"effect\";\nimport { Entity, Sharding } from \"effect/unstable/cluster\";\nimport { Rpc } from \"effect/unstable/rpc\";\nimport { type Primitive, type Transaction } from \"@voidhash/mimic\";\nimport type {\n MimicClusterServerEngineConfig,\n PresenceEntry,\n PresenceEvent,\n ResolvedClusterConfig,\n} from \"./Types\";\nimport type * as Protocol from \"./Protocol\";\nimport { ColdStorageTag, type ColdStorage } from \"./ColdStorage\";\nimport { HotStorageTag, type HotStorage } from \"./HotStorage\";\nimport { MimicAuthServiceTag } from \"./MimicAuthService\";\nimport { MimicServerEngineTag, type MimicServerEngine } from \"./MimicServerEngine\";\nimport {\n DocumentInstance,\n type DocumentInstance as DocumentInstanceInterface,\n} from \"./DocumentInstance\";\nimport * as Metrics from \"./Metrics\";\n\n// =============================================================================\n// Default Configuration\n// =============================================================================\n\nconst DEFAULT_MAX_IDLE_TIME = Duration.minutes(5);\nconst DEFAULT_MAX_TRANSACTION_HISTORY = 1000;\nconst DEFAULT_SNAPSHOT_INTERVAL = Duration.minutes(5);\nconst DEFAULT_SNAPSHOT_THRESHOLD = 100;\nconst DEFAULT_SNAPSHOT_IDLE_TIMEOUT = Duration.seconds(30);\nconst DEFAULT_SHARD_GROUP = \"mimic-documents\";\n\n// =============================================================================\n// RPC Schemas\n// =============================================================================\n\n/**\n * Schema for encoded transaction (wire format)\n */\nconst EncodedTransactionSchema = Schema.Struct({\n id: Schema.String,\n ops: Schema.Array(Schema.Any),\n});\n\n/**\n * Schema for submit result\n */\nconst SubmitResultSchema = Schema.Union([\n Schema.Struct({\n success: Schema.Literal(true),\n version: Schema.Number,\n }),\n Schema.Struct({\n success: Schema.Literal(false),\n reason: Schema.String,\n }),\n]);\n\n/**\n * Schema for snapshot response\n */\nconst SnapshotResponseSchema = Schema.Struct({\n state: Schema.Any,\n version: Schema.Number,\n});\n\n/**\n * Schema for presence entry\n */\nconst PresenceEntrySchema = Schema.Struct({\n data: Schema.Any,\n userId: Schema.optional(Schema.String),\n});\n\n/**\n * Schema for presence snapshot response\n */\nconst PresenceSnapshotResponseSchema = Schema.Struct({\n presences: Schema.Record(Schema.String, PresenceEntrySchema),\n});\n\n/**\n * Schema for presence event\n */\nconst PresenceEventSchema = Schema.Union([\n Schema.Struct({\n type: Schema.Literal(\"presence_update\"),\n id: Schema.String,\n data: Schema.Any,\n userId: Schema.optional(Schema.String),\n }),\n Schema.Struct({\n type: Schema.Literal(\"presence_remove\"),\n id: Schema.String,\n }),\n]);\n\n/**\n * Schema for server message (for broadcasts)\n */\nconst ServerMessageSchema = Schema.Any;\n\n// =============================================================================\n// Mimic Document Entity Definition\n// =============================================================================\n\n/**\n * Define the Mimic Document Entity with its RPC protocol.\n * This entity handles document operations for a single documentId.\n */\nconst MimicDocumentEntity = Entity.make(\"MimicDocument\", [\n // Submit a transaction\n Rpc.make(\"Submit\", {\n payload: { transaction: EncodedTransactionSchema },\n success: SubmitResultSchema,\n }),\n\n // Get document snapshot (flat state)\n Rpc.make(\"GetSnapshot\", {\n success: SnapshotResponseSchema,\n }),\n\n // Get tree-like snapshot for rendering\n Rpc.make(\"GetTreeSnapshot\", {\n success: Schema.Any,\n }),\n\n // Touch document to prevent idle GC\n Rpc.make(\"Touch\", {\n success: Schema.Void,\n }),\n\n // Set presence for a connection\n Rpc.make(\"SetPresence\", {\n payload: {\n connectionId: Schema.String,\n entry: PresenceEntrySchema,\n },\n success: Schema.Void,\n }),\n\n // Remove presence for a connection\n Rpc.make(\"RemovePresence\", {\n payload: { connectionId: Schema.String },\n success: Schema.Void,\n }),\n\n // Get presence snapshot\n Rpc.make(\"GetPresenceSnapshot\", {\n success: PresenceSnapshotResponseSchema,\n }),\n]);\n\n// =============================================================================\n// Entity State Types\n// =============================================================================\n\n/**\n * Entity state that wraps DocumentInstance and adds presence management\n */\ninterface EntityState<TSchema extends Primitive.AnyPrimitive> {\n readonly instance: DocumentInstanceInterface<TSchema>;\n readonly presences: HashMap.HashMap<string, PresenceEntry>;\n readonly presencePubSub: PubSub.PubSub<PresenceEvent>;\n}\n\n// =============================================================================\n// Config Context Tag\n// =============================================================================\n\n/**\n * Context tag for cluster engine configuration\n */\nclass MimicClusterConfigTag extends ServiceMap.Service<MimicClusterConfigTag, ResolvedClusterConfig<Primitive.AnyPrimitive>>()(\n \"@voidhash/mimic-effect/MimicClusterConfig\"\n) {}\n\n// =============================================================================\n// Resolve Configuration\n// =============================================================================\n\nconst resolveClusterConfig = <TSchema extends Primitive.AnyPrimitive>(\n config: MimicClusterServerEngineConfig<TSchema>\n): ResolvedClusterConfig<TSchema> => ({\n schema: config.schema,\n initial: config.initial,\n presence: config.presence,\n maxIdleTime: config.maxIdleTime\n ? Duration.fromInputUnsafe(config.maxIdleTime)\n : DEFAULT_MAX_IDLE_TIME,\n maxTransactionHistory:\n config.maxTransactionHistory ?? DEFAULT_MAX_TRANSACTION_HISTORY,\n snapshot: {\n interval: config.snapshot?.interval\n ? Duration.fromInputUnsafe(config.snapshot.interval)\n : DEFAULT_SNAPSHOT_INTERVAL,\n transactionThreshold:\n config.snapshot?.transactionThreshold ?? DEFAULT_SNAPSHOT_THRESHOLD,\n idleTimeout: config.snapshot?.idleTimeout\n ? Duration.fromInputUnsafe(config.snapshot.idleTimeout)\n : DEFAULT_SNAPSHOT_IDLE_TIMEOUT,\n },\n shardGroup: config.shardGroup ?? DEFAULT_SHARD_GROUP,\n});\n\n// =============================================================================\n// Helper to decode/encode transactions\n// =============================================================================\n\n/**\n * Decode an encoded transaction to a Transaction object\n */\nconst decodeTransaction = (\n encoded: { id: string; ops: readonly unknown[] }\n): Transaction.Transaction => {\n // Import Transaction dynamically to avoid circular deps\n const { Transaction } = require(\"@voidhash/mimic\");\n return Transaction.decode(encoded as Transaction.EncodedTransaction);\n};\n\n/**\n * Encode a Transaction to wire format\n */\nconst encodeTransaction = (\n tx: Transaction.Transaction\n): { id: string; ops: readonly unknown[] } => {\n const { Transaction } = require(\"@voidhash/mimic\");\n return Transaction.encode(tx);\n};\n\n// =============================================================================\n// Entity Handler Factory\n// =============================================================================\n\n/**\n * Create the entity handler for MimicDocument\n */\nconst createEntityHandler = <TSchema extends Primitive.AnyPrimitive>(\n config: ResolvedClusterConfig<TSchema>,\n coldStorage: ColdStorage,\n hotStorage: HotStorage\n) =>\n Effect.fn(\"cluster.entity.handler.create\")(function* () {\n // Get entity address to determine documentId\n const address = yield* Entity.CurrentAddress;\n const documentId = address.entityId;\n\n // Create DocumentInstance (fatal if unavailable - entity cannot start)\n const instance = yield* DocumentInstance.make(\n documentId,\n {\n schema: config.schema,\n initial: config.initial,\n maxTransactionHistory: config.maxTransactionHistory,\n snapshot: config.snapshot,\n },\n coldStorage,\n hotStorage\n ).pipe(Effect.orDie);\n\n // Create presence PubSub and state ref\n const presencePubSub = yield* PubSub.unbounded<PresenceEvent>();\n const stateRef = yield* Ref.make<EntityState<TSchema>>({\n instance,\n presences: HashMap.empty(),\n presencePubSub,\n });\n\n // Cleanup on entity finalization\n yield* Effect.addFinalizer(() =>\n Effect.fn(\"cluster.entity.finalize\")(function* () {\n // Best effort save - don't fail shutdown if storage is unavailable\n yield* Effect[\"catch\"](instance.saveSnapshot(), (e) =>\n Effect.logError(\"Failed to save snapshot during entity finalization\", {\n documentId,\n error: e,\n })\n );\n yield* Metric.update(Metrics.documentsActive, -1);\n yield* Metric.update(Metrics.documentsEvicted, 1);\n yield* Effect.logDebug(\"Entity finalized\", { documentId });\n })()\n );\n\n // Start periodic snapshot fiber for this entity\n const idleTimeoutMs = Duration.toMillis(config.snapshot.idleTimeout);\n if (idleTimeoutMs > 0) {\n const snapshotLoop = Effect.fn(\"cluster.entity.snapshot.loop\")(function* () {\n const needs = yield* instance.needsSnapshot();\n if (needs) {\n yield* Effect[\"catch\"](instance.saveSnapshot(), (e) =>\n Effect.logWarning(\"Periodic snapshot failed in cluster entity\", {\n documentId,\n error: e,\n })\n );\n yield* Metric.update(Metrics.storageIdleSnapshots, 1);\n }\n });\n\n // Run every idleTimeout\n yield* snapshotLoop().pipe(\n Effect.repeat(Schedule.spaced(config.snapshot.idleTimeout)),\n Effect.forkChild\n );\n }\n\n // Return RPC handlers\n return {\n Submit: Effect.fn(\"cluster.document.transaction.submit\")(function* ({\n payload,\n }) {\n // Decode transaction\n const transaction = decodeTransaction(payload.transaction);\n\n // Use DocumentInstance's submit method, catching storage errors\n return yield* instance.submit(transaction).pipe(\n Effect[\"catch\"]((error) =>\n Effect.succeed({\n success: false as const,\n reason: `Storage error: ${String(error)}`,\n })\n )\n );\n }),\n\n GetSnapshot: Effect.fn(\"cluster.document.snapshot.get\")(function* () {\n return instance.getSnapshot();\n }),\n\n GetTreeSnapshot: Effect.fn(\"cluster.document.tree-snapshot.get\")(function* () {\n return instance.toSnapshot();\n }),\n\n Touch: Effect.fn(\"cluster.document.touch\")(function* () {\n yield* instance.touch();\n }),\n\n SetPresence: Effect.fn(\"cluster.presence.set\")(function* ({ payload }) {\n const { connectionId, entry } = payload;\n\n yield* Ref.update(stateRef, (s) => ({\n ...s,\n presences: HashMap.set(s.presences, connectionId, entry),\n }));\n\n yield* Metric.update(Metrics.presenceUpdates, 1);\n yield* Metric.update(Metrics.presenceActive, 1);\n\n const state = yield* Ref.get(stateRef);\n const event: PresenceEvent = {\n type: \"presence_update\",\n id: connectionId,\n data: entry.data,\n userId: entry.userId,\n };\n yield* PubSub.publish(state.presencePubSub, event);\n }),\n\n RemovePresence: Effect.fn(\"cluster.presence.remove\")(function* ({\n payload,\n }) {\n const { connectionId } = payload;\n const state = yield* Ref.get(stateRef);\n\n if (!HashMap.has(state.presences, connectionId)) {\n return;\n }\n\n yield* Ref.update(stateRef, (s) => ({\n ...s,\n presences: HashMap.remove(s.presences, connectionId),\n }));\n\n yield* Metric.update(Metrics.presenceActive, -1);\n\n const event: PresenceEvent = {\n type: \"presence_remove\",\n id: connectionId,\n };\n yield* PubSub.publish(state.presencePubSub, event);\n }),\n\n GetPresenceSnapshot: Effect.fn(\"cluster.presence.snapshot.get\")(\n function* () {\n const state = yield* Ref.get(stateRef);\n const presences: Record<string, PresenceEntry> = {};\n for (const [id, entry] of state.presences) {\n presences[id] = entry;\n }\n return { presences };\n }\n ),\n };\n })();\n\n// =============================================================================\n// Subscription Store (for managing subscriptions at the gateway level)\n// =============================================================================\n\n/**\n * Store for managing document subscriptions\n * This is needed because cluster entities don't support streaming directly\n */\ninterface SubscriptionStore {\n readonly getOrCreatePubSub: (\n documentId: string\n ) => Effect.Effect<PubSub.PubSub<Protocol.ServerMessage>>;\n readonly getOrCreatePresencePubSub: (\n documentId: string\n ) => Effect.Effect<PubSub.PubSub<PresenceEvent>>;\n}\n\nclass SubscriptionStoreTag extends ServiceMap.Service<SubscriptionStoreTag, SubscriptionStore>()(\n \"@voidhash/mimic-effect/SubscriptionStore\"\n) {}\n\nconst subscriptionStoreLayer = Layer.effect(\n SubscriptionStoreTag,\n Effect.fn(\"cluster.subscriptions.layer.create\")(function* () {\n const documentPubSubs = yield* Ref.make(\n HashMap.empty<string, PubSub.PubSub<Protocol.ServerMessage>>()\n );\n const presencePubSubs = yield* Ref.make(\n HashMap.empty<string, PubSub.PubSub<PresenceEvent>>()\n );\n\n return {\n getOrCreatePubSub: Effect.fn(\n \"cluster.subscriptions.pubsub.get-or-create\"\n )(function* (documentId: string) {\n const current = yield* Ref.get(documentPubSubs);\n const existing = HashMap.get(current, documentId);\n if (existing._tag === \"Some\") {\n return existing.value;\n }\n\n const pubsub = yield* PubSub.unbounded<Protocol.ServerMessage>();\n yield* Ref.update(documentPubSubs, (map) =>\n HashMap.set(map, documentId, pubsub)\n );\n return pubsub;\n }),\n\n getOrCreatePresencePubSub: Effect.fn(\n \"cluster.subscriptions.presence-pubsub.get-or-create\"\n )(function* (documentId: string) {\n const current = yield* Ref.get(presencePubSubs);\n const existing = HashMap.get(current, documentId);\n if (existing._tag === \"Some\") {\n return existing.value;\n }\n\n const pubsub = yield* PubSub.unbounded<PresenceEvent>();\n yield* Ref.update(presencePubSubs, (map) =>\n HashMap.set(map, documentId, pubsub)\n );\n return pubsub;\n }),\n };\n })()\n);\n\n// =============================================================================\n// Factory\n// =============================================================================\n\n/**\n * Create a MimicClusterServerEngine layer.\n *\n * This creates a clustered document management service using Effect Cluster.\n * Each document becomes a cluster Entity with automatic sharding and failover.\n *\n * @example\n * ```typescript\n * // 1. Create the engine\n * const Engine = MimicClusterServerEngine.make({\n * schema: DocSchema,\n * initial: { title: \"Untitled\" },\n * presence: CursorPresence,\n * maxIdleTime: \"5 minutes\",\n * snapshot: { interval: \"5 minutes\", transactionThreshold: 100 },\n * shardGroup: \"documents\",\n * })\n *\n * // 2. Create the WebSocket route\n * const MimicRoute = MimicServer.layerHttpLayerRouter({\n * path: \"/mimic\",\n * })\n *\n * // 3. Wire together with cluster infrastructure\n * const MimicLive = MimicRoute.pipe(\n * Layer.provide(Engine),\n * Layer.provide(ColdStorage.S3.make(...)),\n * Layer.provide(HotStorage.Redis.make(...)),\n * Layer.provide(MimicAuthService.make(...)),\n * Layer.provide(ClusterInfrastructure),\n * )\n * ```\n */\nexport const make = <TSchema extends Primitive.AnyPrimitive>(\n config: MimicClusterServerEngineConfig<TSchema>\n): Layer.Layer<\n MimicServerEngineTag,\n never,\n ColdStorageTag | HotStorageTag | MimicAuthServiceTag | Sharding.Sharding\n> => {\n const resolvedConfig = resolveClusterConfig(config);\n\n // Create config layer\n const configLayer = Layer.succeed(\n MimicClusterConfigTag,\n resolvedConfig as ResolvedClusterConfig<Primitive.AnyPrimitive>\n );\n\n // Create entity layer that registers with sharding\n const entityLayer = MimicDocumentEntity.toLayer(\n Effect.gen(function* () {\n const clusterConfig = yield* MimicClusterConfigTag;\n const coldStorage = yield* ColdStorageTag;\n const hotStorage = yield* HotStorageTag;\n\n return yield* createEntityHandler(\n clusterConfig as ResolvedClusterConfig<TSchema>,\n coldStorage,\n hotStorage\n );\n }),\n {\n maxIdleTime: resolvedConfig.maxIdleTime,\n concurrency: 1, // Sequential message processing per document\n mailboxCapacity: 4096,\n }\n );\n\n // Create the engine service\n const engineLayer = Layer.effect(\n MimicServerEngineTag,\n Effect.gen(function* () {\n // Get entity client maker\n const makeClient = yield* MimicDocumentEntity.client;\n\n // Get subscription store\n const subscriptionStore = yield* SubscriptionStoreTag;\n\n const engine: MimicServerEngine = {\n submit: (documentId, transaction) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n const encodedTx = encodeTransaction(transaction);\n const result = yield* client.Submit({\n transaction: encodedTx as { id: string; ops: unknown[] },\n }).pipe(\n Effect[\"catch\"]((error) =>\n Effect.succeed({\n success: false as const,\n reason: `Cluster error: ${String(error)}`,\n })\n )\n );\n\n // Broadcast to local subscribers if success\n if (result.success) {\n const pubsub =\n yield* subscriptionStore.getOrCreatePubSub(documentId);\n yield* PubSub.publish(pubsub, {\n type: \"transaction\",\n transaction,\n version: result.version,\n } as Protocol.ServerMessage);\n }\n\n return result;\n }),\n\n getSnapshot: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n return yield* client.GetSnapshot(undefined as void).pipe(Effect.orDie);\n }),\n\n getTreeSnapshot: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n return yield* client.GetTreeSnapshot(undefined as void).pipe(Effect.orDie);\n }),\n\n subscribe: (documentId) =>\n Effect.gen(function* () {\n const pubsub =\n yield* subscriptionStore.getOrCreatePubSub(documentId);\n return Stream.fromPubSub(pubsub);\n }),\n\n touch: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n yield* client.Touch(undefined as void).pipe(Effect.orDie);\n }),\n\n getPresenceSnapshot: (documentId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n return yield* client.GetPresenceSnapshot(undefined as void).pipe(Effect.orDie);\n }),\n\n setPresence: (documentId, connectionId, entry) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n yield* client.SetPresence({ connectionId, entry }).pipe(Effect.orDie);\n\n // Broadcast to local presence subscribers\n const pubsub =\n yield* subscriptionStore.getOrCreatePresencePubSub(documentId);\n yield* PubSub.publish(pubsub, {\n type: \"presence_update\",\n id: connectionId,\n data: entry.data,\n userId: entry.userId,\n });\n }),\n\n removePresence: (documentId, connectionId) =>\n Effect.gen(function* () {\n const client = makeClient(documentId);\n yield* client.RemovePresence({ connectionId }).pipe(Effect.orDie);\n\n // Broadcast to local presence subscribers\n const pubsub =\n yield* subscriptionStore.getOrCreatePresencePubSub(documentId);\n yield* PubSub.publish(pubsub, {\n type: \"presence_remove\",\n id: connectionId,\n });\n }),\n\n subscribePresence: (documentId) =>\n Effect.gen(function* () {\n const pubsub =\n yield* subscriptionStore.getOrCreatePresencePubSub(documentId);\n return Stream.fromPubSub(pubsub);\n }),\n\n config: resolvedConfig as ResolvedClusterConfig<Primitive.AnyPrimitive>,\n };\n\n return engine;\n })\n );\n\n // Compose all layers\n return Layer.mergeAll(entityLayer, engineLayer).pipe(\n Layer.provideMerge(subscriptionStoreLayer),\n Layer.provideMerge(configLayer)\n );\n};\n\n// =============================================================================\n// Re-export namespace\n// =============================================================================\n\nexport const MimicClusterServerEngine = {\n make,\n};\n"],"mappings":"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"}