@rivetkit/effect 0.0.0-sqlite-uds.37f9e48 → 0.0.0-sqlite-profiling-compat.4a9a623
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Actor.d.ts +3 -2
- package/dist/Actor.d.ts.map +1 -1
- package/dist/Actor.js +2 -2
- package/dist/Actor.js.map +1 -1
- package/dist/Client.d.ts.map +1 -1
- package/dist/Client.js +4 -6
- package/dist/Client.js.map +1 -1
- package/dist/Logger.d.ts +29 -0
- package/dist/Logger.d.ts.map +1 -0
- package/dist/Logger.js +31 -0
- package/dist/Logger.js.map +1 -0
- package/dist/Registry.d.ts +7 -69
- package/dist/Registry.d.ts.map +1 -1
- package/dist/Registry.js +40 -93
- package/dist/Registry.js.map +1 -1
- package/dist/RivetError.d.ts +3 -18
- package/dist/RivetError.d.ts.map +1 -1
- package/dist/RivetError.js +0 -31
- package/dist/RivetError.js.map +1 -1
- package/dist/State.d.ts +56 -92
- package/dist/State.d.ts.map +1 -1
- package/dist/State.js +57 -51
- package/dist/State.js.map +1 -1
- package/dist/internal/ActorInstanceManager.d.ts.map +1 -1
- package/dist/internal/ActorInstanceManager.js +4 -4
- package/dist/internal/ActorInstanceManager.js.map +1 -1
- package/dist/internal/ActorStateAdapter.d.ts +1 -1
- package/dist/internal/ActorStateAdapter.d.ts.map +1 -1
- package/dist/internal/ActorStateAdapter.js +7 -2
- package/dist/internal/ActorStateAdapter.js.map +1 -1
- package/dist/internal/StateOptions.d.ts +0 -1
- package/dist/internal/StateOptions.d.ts.map +1 -1
- package/dist/internal/logging.d.ts +7 -6
- package/dist/internal/logging.d.ts.map +1 -1
- package/dist/internal/logging.js +102 -78
- package/dist/internal/logging.js.map +1 -1
- package/dist/mod.d.ts +1 -1
- package/dist/mod.d.ts.map +1 -1
- package/dist/mod.js +1 -1
- package/dist/mod.js.map +1 -1
- package/package.json +8 -3
- package/src/Actor.test-d.ts +0 -32
- package/src/Actor.ts +4 -29
- package/src/Client.test.ts +18 -21
- package/src/Client.ts +4 -6
- package/src/Logger.ts +43 -0
- package/src/Registry.test.ts +11 -7
- package/src/Registry.ts +50 -116
- package/src/RivetError.test.ts +0 -11
- package/src/RivetError.ts +0 -37
- package/src/State.test.ts +4 -163
- package/src/State.ts +97 -293
- package/src/internal/ActorInstanceManager.ts +10 -4
- package/src/internal/ActorStateAdapter.ts +11 -5
- package/src/internal/StateOptions.ts +0 -4
- package/src/internal/logging.test.ts +88 -65
- package/src/internal/logging.ts +143 -103
- package/src/mod.ts +1 -1
- package/dist/RivetLogger.d.ts +0 -41
- package/dist/RivetLogger.d.ts.map +0 -1
- package/dist/RivetLogger.js +0 -41
- package/dist/RivetLogger.js.map +0 -1
- package/src/RivetLogger.ts +0 -60
package/src/State.test.ts
CHANGED
|
@@ -36,26 +36,6 @@ describe("State", () => {
|
|
|
36
36
|
}),
|
|
37
37
|
);
|
|
38
38
|
|
|
39
|
-
it.effect(
|
|
40
|
-
"getAndSet returns the previous value and commits the new value",
|
|
41
|
-
() =>
|
|
42
|
-
Effect.gen(function* () {
|
|
43
|
-
const { s, cell } = yield* makeCellState(10);
|
|
44
|
-
const previous = yield* State.getAndSet(s, 15);
|
|
45
|
-
assert.strictEqual(previous, 10);
|
|
46
|
-
assert.strictEqual(cell.value, 15);
|
|
47
|
-
}),
|
|
48
|
-
);
|
|
49
|
-
|
|
50
|
-
it.effect("setAndGet returns the committed value", () =>
|
|
51
|
-
Effect.gen(function* () {
|
|
52
|
-
const { s, cell } = yield* makeCellState(10);
|
|
53
|
-
const next = yield* State.setAndGet(s, 15);
|
|
54
|
-
assert.strictEqual(next, 15);
|
|
55
|
-
assert.strictEqual(cell.value, 15);
|
|
56
|
-
}),
|
|
57
|
-
);
|
|
58
|
-
|
|
59
39
|
it.effect("update applies f over read/write", () =>
|
|
60
40
|
Effect.gen(function* () {
|
|
61
41
|
const { s, cell } = yield* makeCellState(10);
|
|
@@ -64,38 +44,6 @@ describe("State", () => {
|
|
|
64
44
|
}),
|
|
65
45
|
);
|
|
66
46
|
|
|
67
|
-
it.effect("updateEffect applies an Effectful f over read/write", () =>
|
|
68
|
-
Effect.gen(function* () {
|
|
69
|
-
const { s, cell } = yield* makeCellState(10);
|
|
70
|
-
yield* State.updateEffect(s, (n) => Effect.succeed(n + 5));
|
|
71
|
-
assert.strictEqual(cell.value, 15);
|
|
72
|
-
}),
|
|
73
|
-
);
|
|
74
|
-
|
|
75
|
-
it.effect(
|
|
76
|
-
"getAndUpdate returns the previous value and commits the new value",
|
|
77
|
-
() =>
|
|
78
|
-
Effect.gen(function* () {
|
|
79
|
-
const { s, cell } = yield* makeCellState(10);
|
|
80
|
-
const previous = yield* State.getAndUpdate(s, (n) => n + 5);
|
|
81
|
-
assert.strictEqual(previous, 10);
|
|
82
|
-
assert.strictEqual(cell.value, 15);
|
|
83
|
-
}),
|
|
84
|
-
);
|
|
85
|
-
|
|
86
|
-
it.effect(
|
|
87
|
-
"getAndUpdateEffect returns the previous value and commits the new value",
|
|
88
|
-
() =>
|
|
89
|
-
Effect.gen(function* () {
|
|
90
|
-
const { s, cell } = yield* makeCellState(10);
|
|
91
|
-
const previous = yield* State.getAndUpdateEffect(s, (n) =>
|
|
92
|
-
Effect.succeed(n + 5),
|
|
93
|
-
);
|
|
94
|
-
assert.strictEqual(previous, 10);
|
|
95
|
-
assert.strictEqual(cell.value, 15);
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
98
|
-
|
|
99
47
|
it.effect("updateAndGet returns the new value and commits it", () =>
|
|
100
48
|
Effect.gen(function* () {
|
|
101
49
|
const { s, cell } = yield* makeCellState(10);
|
|
@@ -105,17 +53,6 @@ describe("State", () => {
|
|
|
105
53
|
}),
|
|
106
54
|
);
|
|
107
55
|
|
|
108
|
-
it.effect("updateAndGetEffect returns the new value and commits it", () =>
|
|
109
|
-
Effect.gen(function* () {
|
|
110
|
-
const { s, cell } = yield* makeCellState(10);
|
|
111
|
-
const next = yield* State.updateAndGetEffect(s, (n) =>
|
|
112
|
-
Effect.succeed(n + 5),
|
|
113
|
-
);
|
|
114
|
-
assert.strictEqual(next, 15);
|
|
115
|
-
assert.strictEqual(cell.value, 15);
|
|
116
|
-
}),
|
|
117
|
-
);
|
|
118
|
-
|
|
119
56
|
it.effect("modify returns B and commits the new value", () =>
|
|
120
57
|
Effect.gen(function* () {
|
|
121
58
|
const { s, cell } = yield* makeCellState("a");
|
|
@@ -128,17 +65,6 @@ describe("State", () => {
|
|
|
128
65
|
}),
|
|
129
66
|
);
|
|
130
67
|
|
|
131
|
-
it.effect("modifyEffect returns B and commits the new value", () =>
|
|
132
|
-
Effect.gen(function* () {
|
|
133
|
-
const { s, cell } = yield* makeCellState("a");
|
|
134
|
-
const b = yield* State.modifyEffect(s, (str) =>
|
|
135
|
-
Effect.succeed([str.length, `${str}b`] as const),
|
|
136
|
-
);
|
|
137
|
-
assert.strictEqual(b, 1);
|
|
138
|
-
assert.strictEqual(cell.value, "ab");
|
|
139
|
-
}),
|
|
140
|
-
);
|
|
141
|
-
|
|
142
68
|
it.effect(
|
|
143
69
|
"update is atomic across concurrent fibers (no lost updates)",
|
|
144
70
|
() =>
|
|
@@ -163,7 +89,7 @@ describe("State", () => {
|
|
|
163
89
|
);
|
|
164
90
|
assert.deepStrictEqual(initial, [0]);
|
|
165
91
|
|
|
166
|
-
|
|
92
|
+
State.publishUnsafe(s, 7);
|
|
167
93
|
const later = yield* State.changes(s).pipe(
|
|
168
94
|
Stream.take(1),
|
|
169
95
|
Stream.runCollect,
|
|
@@ -177,17 +103,11 @@ describe("State", () => {
|
|
|
177
103
|
const { s } = yield* makeCellState(0);
|
|
178
104
|
yield* Effect.scoped(
|
|
179
105
|
Effect.gen(function* () {
|
|
180
|
-
const sub = yield* PubSub.subscribe(
|
|
181
|
-
s[State.RuntimeTypeId].pubsub,
|
|
182
|
-
);
|
|
106
|
+
const sub = yield* PubSub.subscribe(s.pubsub);
|
|
183
107
|
assert.strictEqual(yield* PubSub.take(sub), 0);
|
|
184
108
|
|
|
185
|
-
yield*
|
|
186
|
-
|
|
187
|
-
);
|
|
188
|
-
yield* s[State.RuntimeTypeId].publishEffect(
|
|
189
|
-
Effect.succeed(2),
|
|
190
|
-
);
|
|
109
|
+
yield* State.publish(s, 1);
|
|
110
|
+
yield* State.publish(s, 2);
|
|
191
111
|
assert.strictEqual(yield* PubSub.take(sub), 1);
|
|
192
112
|
assert.strictEqual(yield* PubSub.take(sub), 2);
|
|
193
113
|
}),
|
|
@@ -195,19 +115,6 @@ describe("State", () => {
|
|
|
195
115
|
}),
|
|
196
116
|
);
|
|
197
117
|
|
|
198
|
-
it.effect("shuts down the backing pubsub when its scope closes", () =>
|
|
199
|
-
Effect.gen(function* () {
|
|
200
|
-
const pubsub = yield* Effect.scoped(
|
|
201
|
-
Effect.gen(function* () {
|
|
202
|
-
const { s } = yield* makeCellState(0);
|
|
203
|
-
return s[State.RuntimeTypeId].pubsub;
|
|
204
|
-
}),
|
|
205
|
-
);
|
|
206
|
-
|
|
207
|
-
assert.isTrue(yield* PubSub.isShutdown(pubsub));
|
|
208
|
-
}),
|
|
209
|
-
);
|
|
210
|
-
|
|
211
118
|
it.effect("set does NOT auto-publish — the runtime does", () =>
|
|
212
119
|
Effect.gen(function* () {
|
|
213
120
|
const { s } = yield* makeCellState(0);
|
|
@@ -239,61 +146,6 @@ describe("State", () => {
|
|
|
239
146
|
|
|
240
147
|
yield* s.pipe(State.update((n) => n * 2));
|
|
241
148
|
assert.strictEqual(yield* State.get(s), 10);
|
|
242
|
-
|
|
243
|
-
yield* s.pipe(State.updateEffect((n) => Effect.succeed(n + 1)));
|
|
244
|
-
assert.strictEqual(yield* State.get(s), 11);
|
|
245
|
-
}),
|
|
246
|
-
);
|
|
247
|
-
|
|
248
|
-
it.effect("supports instance methods", () =>
|
|
249
|
-
Effect.gen(function* () {
|
|
250
|
-
const { s, cell } = yield* makeCellState(0);
|
|
251
|
-
assert.strictEqual(yield* s.get, 0);
|
|
252
|
-
|
|
253
|
-
yield* s.set(5);
|
|
254
|
-
assert.strictEqual(cell.value, 5);
|
|
255
|
-
|
|
256
|
-
const beforeSet = yield* s.getAndSet(6);
|
|
257
|
-
assert.strictEqual(beforeSet, 5);
|
|
258
|
-
assert.strictEqual(cell.value, 6);
|
|
259
|
-
|
|
260
|
-
const afterSet = yield* s.setAndGet(7);
|
|
261
|
-
assert.strictEqual(afterSet, 7);
|
|
262
|
-
assert.strictEqual(cell.value, 7);
|
|
263
|
-
|
|
264
|
-
yield* s.update((n) => n * 2);
|
|
265
|
-
assert.strictEqual(yield* s.get, 14);
|
|
266
|
-
|
|
267
|
-
yield* s.updateEffect((n) => Effect.succeed(n + 1));
|
|
268
|
-
assert.strictEqual(yield* s.get, 15);
|
|
269
|
-
|
|
270
|
-
const previousUpdate = yield* s.getAndUpdate((n) => n + 1);
|
|
271
|
-
assert.strictEqual(previousUpdate, 15);
|
|
272
|
-
assert.strictEqual(yield* s.get, 16);
|
|
273
|
-
|
|
274
|
-
const previousEffectUpdate = yield* s.getAndUpdateEffect((n) =>
|
|
275
|
-
Effect.succeed(n + 1),
|
|
276
|
-
);
|
|
277
|
-
assert.strictEqual(previousEffectUpdate, 16);
|
|
278
|
-
assert.strictEqual(yield* s.get, 17);
|
|
279
|
-
|
|
280
|
-
const next = yield* s.updateAndGet((n) => n + 1);
|
|
281
|
-
assert.strictEqual(next, 18);
|
|
282
|
-
|
|
283
|
-
const effectNext = yield* s.updateAndGetEffect((n) =>
|
|
284
|
-
Effect.succeed(n + 1),
|
|
285
|
-
);
|
|
286
|
-
assert.strictEqual(effectNext, 19);
|
|
287
|
-
|
|
288
|
-
const previous = yield* s.modify((n) => [n, n + 1] as const);
|
|
289
|
-
assert.strictEqual(previous, 19);
|
|
290
|
-
assert.strictEqual(yield* s.get, 20);
|
|
291
|
-
|
|
292
|
-
const effectPrevious = yield* s.modifyEffect((n) =>
|
|
293
|
-
Effect.succeed([n, n + 1] as const),
|
|
294
|
-
);
|
|
295
|
-
assert.strictEqual(effectPrevious, 20);
|
|
296
|
-
assert.strictEqual(yield* s.get, 21);
|
|
297
149
|
}),
|
|
298
150
|
);
|
|
299
151
|
|
|
@@ -326,15 +178,4 @@ describe("State", () => {
|
|
|
326
178
|
assert.isTrue(Exit.isFailure(exit));
|
|
327
179
|
}),
|
|
328
180
|
);
|
|
329
|
-
|
|
330
|
-
it.effect("Effectful update failure does not write", () =>
|
|
331
|
-
Effect.gen(function* () {
|
|
332
|
-
const { s, cell } = yield* makeCellState(0);
|
|
333
|
-
const exit = yield* Effect.exit(
|
|
334
|
-
State.updateEffect(s, () => Effect.fail("boom" as const)),
|
|
335
|
-
);
|
|
336
|
-
assert.isTrue(Exit.isFailure(exit));
|
|
337
|
-
assert.strictEqual(cell.value, 0);
|
|
338
|
-
}),
|
|
339
|
-
);
|
|
340
181
|
});
|
package/src/State.ts
CHANGED
|
@@ -26,7 +26,6 @@ import {
|
|
|
26
26
|
Predicate,
|
|
27
27
|
PubSub,
|
|
28
28
|
Semaphore,
|
|
29
|
-
Scope,
|
|
30
29
|
Stream,
|
|
31
30
|
type Types,
|
|
32
31
|
} from "effect";
|
|
@@ -34,15 +33,6 @@ import { dual } from "effect/Function";
|
|
|
34
33
|
|
|
35
34
|
const TypeId = "~@rivetkit/effect/State";
|
|
36
35
|
|
|
37
|
-
/**
|
|
38
|
-
* Internal access to `State`'s backing store and publish machinery.
|
|
39
|
-
*
|
|
40
|
-
* @internal
|
|
41
|
-
*/
|
|
42
|
-
export const RuntimeTypeId: unique symbol = Symbol.for(
|
|
43
|
-
"~@rivetkit/effect/State/Runtime",
|
|
44
|
-
) as never;
|
|
45
|
-
|
|
46
36
|
/**
|
|
47
37
|
* A view over a persisted state cell with a subscribable change stream.
|
|
48
38
|
*
|
|
@@ -55,97 +45,17 @@ export interface State<A, E = never, R = never>
|
|
|
55
45
|
extends Variance<A, E, R>,
|
|
56
46
|
Pipeable.Pipeable,
|
|
57
47
|
Inspectable.Inspectable {
|
|
58
|
-
/**
|
|
59
|
-
* Retrieves the persisted value.
|
|
60
|
-
*/
|
|
61
|
-
readonly get: Effect.Effect<A, E, R>;
|
|
62
|
-
/**
|
|
63
|
-
* Retrieves the persisted value and sets a new value atomically.
|
|
64
|
-
*/
|
|
65
|
-
readonly getAndSet: (value: A) => Effect.Effect<A, E, R>;
|
|
66
|
-
/**
|
|
67
|
-
* Retrieves the current value and updates it atomically with the result of
|
|
68
|
-
* applying a function.
|
|
69
|
-
*/
|
|
70
|
-
readonly getAndUpdate: (f: (a: A) => A) => Effect.Effect<A, E, R>;
|
|
71
|
-
/**
|
|
72
|
-
* Retrieves the current value and updates it atomically with the result of
|
|
73
|
-
* applying an effectful function.
|
|
74
|
-
*/
|
|
75
|
-
readonly getAndUpdateEffect: <E2, R2>(
|
|
76
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
77
|
-
) => Effect.Effect<A, E | E2, R | R2>;
|
|
78
|
-
/**
|
|
79
|
-
* Modifies atomically with a function that computes a return value and
|
|
80
|
-
* a new value.
|
|
81
|
-
*/
|
|
82
|
-
readonly modify: <B>(
|
|
83
|
-
f: (a: A) => readonly [B, A],
|
|
84
|
-
) => Effect.Effect<B, E, R>;
|
|
85
|
-
/**
|
|
86
|
-
* Modifies atomically with an effectful function that computes a return value
|
|
87
|
-
* and a new value.
|
|
88
|
-
*/
|
|
89
|
-
readonly modifyEffect: <B, E2, R2>(
|
|
90
|
-
f: (a: A) => Effect.Effect<readonly [B, A], E2, R2>,
|
|
91
|
-
) => Effect.Effect<B, E | E2, R | R2>;
|
|
92
|
-
/**
|
|
93
|
-
* Writes the persisted value.
|
|
94
|
-
*/
|
|
95
|
-
readonly set: (value: A) => Effect.Effect<void, E, R>;
|
|
96
|
-
/**
|
|
97
|
-
* Sets the persisted value and returns the new value.
|
|
98
|
-
*/
|
|
99
|
-
readonly setAndGet: (value: A) => Effect.Effect<A, E, R>;
|
|
100
|
-
/**
|
|
101
|
-
* Updates the persisted value with the result of applying a function.
|
|
102
|
-
*/
|
|
103
|
-
readonly update: (f: (a: A) => A) => Effect.Effect<void, E, R>;
|
|
104
|
-
/**
|
|
105
|
-
* Updates the persisted value with the result of applying an effectful function.
|
|
106
|
-
*/
|
|
107
|
-
readonly updateEffect: <E2, R2>(
|
|
108
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
109
|
-
) => Effect.Effect<void, E | E2, R | R2>;
|
|
110
|
-
/**
|
|
111
|
-
* Updates the persisted value with the result of applying an effectful function
|
|
112
|
-
* and returns the new value.
|
|
113
|
-
*/
|
|
114
|
-
readonly updateAndGet: (f: (a: A) => A) => Effect.Effect<A, E, R>;
|
|
115
|
-
/**
|
|
116
|
-
* Updates the persisted value with the result of applying an effectful function
|
|
117
|
-
* and returns the new value.
|
|
118
|
-
*/
|
|
119
|
-
readonly updateAndGetEffect: <E2, R2>(
|
|
120
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
121
|
-
) => Effect.Effect<A, E | E2, R | R2>;
|
|
122
|
-
/**
|
|
123
|
-
* Creates a stream that emits the current persisted value and all subsequent
|
|
124
|
-
* changes.
|
|
125
|
-
*/
|
|
126
|
-
readonly changes: Stream.Stream<A>;
|
|
127
|
-
/**
|
|
128
|
-
* Internal access to `State`'s backing store and publish machinery.
|
|
129
|
-
*
|
|
130
|
-
* @internal
|
|
131
|
-
*/
|
|
132
|
-
readonly [RuntimeTypeId]: StateRuntime<A, E, R>;
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Runtime-only hooks for wiring actor state persistence and change
|
|
137
|
-
* notifications.
|
|
138
|
-
*
|
|
139
|
-
* @internal
|
|
140
|
-
*/
|
|
141
|
-
export interface StateRuntime<A, E = never, R = never> {
|
|
142
|
-
readonly publish: (value: A) => Effect.Effect<boolean>;
|
|
143
|
-
readonly publishEffect: <E2, R2>(
|
|
144
|
-
effect: Effect.Effect<A, E2, R2>,
|
|
145
|
-
) => Effect.Effect<boolean, E2, R2>;
|
|
146
48
|
readonly read: () => Effect.Effect<A, E, R>;
|
|
147
49
|
readonly write: (value: A) => Effect.Effect<void, E, R>;
|
|
148
50
|
readonly pubsub: PubSub.PubSub<A>;
|
|
51
|
+
/**
|
|
52
|
+
* Serializes writes (`set`, `update`, `modify`) so the read/apply/
|
|
53
|
+
* write triple is atomic. The runtime may also use this semaphore
|
|
54
|
+
* to serialize its own decode-and-publish work from
|
|
55
|
+
* `onStateChange`, keeping the change stream's order consistent
|
|
56
|
+
* with the write order.
|
|
57
|
+
*/
|
|
58
|
+
readonly semaphore: Semaphore.Semaphore;
|
|
149
59
|
}
|
|
150
60
|
|
|
151
61
|
export const isState = (u: unknown): u is State<unknown, unknown> =>
|
|
@@ -176,192 +86,47 @@ const Proto = {
|
|
|
176
86
|
* The current value (per `read()`) is published to the pubsub on
|
|
177
87
|
* construction so any subscription obtained later replays it.
|
|
178
88
|
*
|
|
179
|
-
* The
|
|
180
|
-
* `
|
|
89
|
+
* The PubSub is not explicitly shut down — it's reclaimed by GC when
|
|
90
|
+
* the `State` and any subscribers become unreachable.
|
|
181
91
|
*/
|
|
182
92
|
export const make = Effect.fnUntraced(function* <A, E, R>(
|
|
183
93
|
read: () => Effect.Effect<A, E, R>,
|
|
184
94
|
write: (value: A) => Effect.Effect<void, E, R>,
|
|
185
|
-
): Effect.fn.Return<State<A, E, R>, E, R
|
|
95
|
+
): Effect.fn.Return<State<A, E, R>, E, R> {
|
|
186
96
|
const pubsub = yield* PubSub.unbounded<A>({ replay: 1 });
|
|
187
|
-
yield* Effect.addFinalizer(() => PubSub.shutdown(pubsub));
|
|
188
97
|
const initial = yield* read();
|
|
189
|
-
|
|
98
|
+
PubSub.publishUnsafe(pubsub, initial);
|
|
190
99
|
const self = Object.create(Proto);
|
|
191
|
-
|
|
192
|
-
self
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
pubsub,
|
|
196
|
-
publish: (value: A) => PubSub.publish(pubsub, value),
|
|
197
|
-
publishEffect: <E2, R2>(effect: Effect.Effect<A, E2, R2>) =>
|
|
198
|
-
Semaphore.withPermit(
|
|
199
|
-
semaphore,
|
|
200
|
-
Effect.flatMap(effect, (value) =>
|
|
201
|
-
PubSub.publish(pubsub, value),
|
|
202
|
-
),
|
|
203
|
-
),
|
|
204
|
-
};
|
|
205
|
-
self.get = Effect.suspend(() => self[RuntimeTypeId].read());
|
|
206
|
-
self.set = (value: A) => Semaphore.withPermit(semaphore, write(value));
|
|
207
|
-
self.getAndSet = (value: A) =>
|
|
208
|
-
Semaphore.withPermit(
|
|
209
|
-
semaphore,
|
|
210
|
-
Effect.flatMap(read(), (previous) =>
|
|
211
|
-
Effect.as(write(value), previous),
|
|
212
|
-
),
|
|
213
|
-
);
|
|
214
|
-
self.setAndGet = (value: A) =>
|
|
215
|
-
Semaphore.withPermit(semaphore, Effect.as(write(value), value));
|
|
216
|
-
self.update = (f: (a: A) => A) =>
|
|
217
|
-
Semaphore.withPermit(
|
|
218
|
-
semaphore,
|
|
219
|
-
Effect.flatMap(read(), (a) => write(f(a))),
|
|
220
|
-
);
|
|
221
|
-
self.updateEffect = <E2, R2>(f: (a: A) => Effect.Effect<A, E2, R2>) =>
|
|
222
|
-
Semaphore.withPermit(
|
|
223
|
-
semaphore,
|
|
224
|
-
Effect.flatMap(read(), (a) => Effect.flatMap(f(a), write)),
|
|
225
|
-
);
|
|
226
|
-
self.getAndUpdate = (f: (a: A) => A) =>
|
|
227
|
-
Semaphore.withPermit(
|
|
228
|
-
semaphore,
|
|
229
|
-
Effect.flatMap(read(), (previous) =>
|
|
230
|
-
Effect.as(write(f(previous)), previous),
|
|
231
|
-
),
|
|
232
|
-
);
|
|
233
|
-
self.getAndUpdateEffect = <E2, R2>(f: (a: A) => Effect.Effect<A, E2, R2>) =>
|
|
234
|
-
Semaphore.withPermit(
|
|
235
|
-
semaphore,
|
|
236
|
-
Effect.flatMap(read(), (previous) =>
|
|
237
|
-
Effect.flatMap(f(previous), (next) =>
|
|
238
|
-
Effect.as(write(next), previous),
|
|
239
|
-
),
|
|
240
|
-
),
|
|
241
|
-
);
|
|
242
|
-
self.updateAndGet = (f: (a: A) => A) =>
|
|
243
|
-
Semaphore.withPermit(
|
|
244
|
-
semaphore,
|
|
245
|
-
Effect.flatMap(read(), (a) => {
|
|
246
|
-
const next = f(a);
|
|
247
|
-
return Effect.as(write(next), next);
|
|
248
|
-
}),
|
|
249
|
-
);
|
|
250
|
-
self.updateAndGetEffect = <E2, R2>(f: (a: A) => Effect.Effect<A, E2, R2>) =>
|
|
251
|
-
Semaphore.withPermit(
|
|
252
|
-
semaphore,
|
|
253
|
-
Effect.flatMap(read(), (a) =>
|
|
254
|
-
Effect.flatMap(f(a), (next) => Effect.as(write(next), next)),
|
|
255
|
-
),
|
|
256
|
-
);
|
|
257
|
-
self.modify = <B>(f: (a: A) => readonly [B, A]) =>
|
|
258
|
-
Semaphore.withPermit(
|
|
259
|
-
semaphore,
|
|
260
|
-
Effect.flatMap(read(), (a) => {
|
|
261
|
-
const [b, next] = f(a);
|
|
262
|
-
return Effect.as(write(next), b);
|
|
263
|
-
}),
|
|
264
|
-
);
|
|
265
|
-
self.modifyEffect = <B, E2, R2>(
|
|
266
|
-
f: (a: A) => Effect.Effect<readonly [B, A], E2, R2>,
|
|
267
|
-
) =>
|
|
268
|
-
Semaphore.withPermit(
|
|
269
|
-
semaphore,
|
|
270
|
-
Effect.flatMap(read(), (a) =>
|
|
271
|
-
Effect.flatMap(f(a), ([b, next]) => Effect.as(write(next), b)),
|
|
272
|
-
),
|
|
273
|
-
);
|
|
274
|
-
self.changes = Stream.fromPubSub(pubsub);
|
|
100
|
+
self.read = read;
|
|
101
|
+
self.write = write;
|
|
102
|
+
self.pubsub = pubsub;
|
|
103
|
+
self.semaphore = Semaphore.makeUnsafe(1);
|
|
275
104
|
return self;
|
|
276
105
|
});
|
|
277
106
|
|
|
107
|
+
/**
|
|
108
|
+
* Reads the current value.
|
|
109
|
+
*/
|
|
278
110
|
export const get = <A, E, R>(self: State<A, E, R>): Effect.Effect<A, E, R> =>
|
|
279
|
-
self.
|
|
280
|
-
|
|
281
|
-
export const getAndSet: {
|
|
282
|
-
<A>(value: A): <E, R>(self: State<A, E, R>) => Effect.Effect<A, E, R>;
|
|
283
|
-
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<A, E, R>;
|
|
284
|
-
} = dual(
|
|
285
|
-
2,
|
|
286
|
-
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<A, E, R> =>
|
|
287
|
-
self.getAndSet(value),
|
|
288
|
-
);
|
|
289
|
-
|
|
290
|
-
export const getAndUpdate: {
|
|
291
|
-
<A>(f: (a: A) => A): <E, R>(self: State<A, E, R>) => Effect.Effect<A, E, R>;
|
|
292
|
-
<A, E, R>(self: State<A, E, R>, f: (a: A) => A): Effect.Effect<A, E, R>;
|
|
293
|
-
} = dual(
|
|
294
|
-
2,
|
|
295
|
-
<A, E, R>(self: State<A, E, R>, f: (a: A) => A): Effect.Effect<A, E, R> =>
|
|
296
|
-
self.getAndUpdate(f),
|
|
297
|
-
);
|
|
298
|
-
|
|
299
|
-
export const getAndUpdateEffect: {
|
|
300
|
-
<A, E2, R2>(
|
|
301
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
302
|
-
): <E, R>(self: State<A, E, R>) => Effect.Effect<A, E | E2, R | R2>;
|
|
303
|
-
<A, E, R, E2, R2>(
|
|
304
|
-
self: State<A, E, R>,
|
|
305
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
306
|
-
): Effect.Effect<A, E | E2, R | R2>;
|
|
307
|
-
} = dual(
|
|
308
|
-
2,
|
|
309
|
-
<A, E, R, E2, R2>(
|
|
310
|
-
self: State<A, E, R>,
|
|
311
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
312
|
-
): Effect.Effect<A, E | E2, R | R2> => self.getAndUpdateEffect(f),
|
|
313
|
-
);
|
|
314
|
-
|
|
315
|
-
export const modify: {
|
|
316
|
-
<A, B>(
|
|
317
|
-
f: (a: A) => readonly [B, A],
|
|
318
|
-
): <E, R>(self: State<A, E, R>) => Effect.Effect<B, E, R>;
|
|
319
|
-
<A, E, R, B>(
|
|
320
|
-
self: State<A, E, R>,
|
|
321
|
-
f: (a: A) => readonly [B, A],
|
|
322
|
-
): Effect.Effect<B, E, R>;
|
|
323
|
-
} = dual(
|
|
324
|
-
2,
|
|
325
|
-
<A, E, R, B>(
|
|
326
|
-
self: State<A, E, R>,
|
|
327
|
-
f: (a: A) => readonly [B, A],
|
|
328
|
-
): Effect.Effect<B, E, R> => self.modify(f),
|
|
329
|
-
);
|
|
330
|
-
|
|
331
|
-
export const modifyEffect: {
|
|
332
|
-
<A, B, E2, R2>(
|
|
333
|
-
f: (a: A) => Effect.Effect<readonly [B, A], E2, R2>,
|
|
334
|
-
): <E, R>(self: State<A, E, R>) => Effect.Effect<B, E | E2, R | R2>;
|
|
335
|
-
<A, E, R, B, E2, R2>(
|
|
336
|
-
self: State<A, E, R>,
|
|
337
|
-
f: (a: A) => Effect.Effect<readonly [B, A], E2, R2>,
|
|
338
|
-
): Effect.Effect<B, E | E2, R | R2>;
|
|
339
|
-
} = dual(
|
|
340
|
-
2,
|
|
341
|
-
<A, E, R, B, E2, R2>(
|
|
342
|
-
self: State<A, E, R>,
|
|
343
|
-
f: (a: A) => Effect.Effect<readonly [B, A], E2, R2>,
|
|
344
|
-
): Effect.Effect<B, E | E2, R | R2> => self.modifyEffect(f),
|
|
345
|
-
);
|
|
111
|
+
self.read();
|
|
346
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Replaces the value. Serialized with `update` / `modify` so writes
|
|
115
|
+
* happen in invocation order.
|
|
116
|
+
*/
|
|
347
117
|
export const set: {
|
|
348
118
|
<A>(value: A): <E, R>(self: State<A, E, R>) => Effect.Effect<void, E, R>;
|
|
349
119
|
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<void, E, R>;
|
|
350
120
|
} = dual(
|
|
351
121
|
2,
|
|
352
122
|
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<void, E, R> =>
|
|
353
|
-
self.
|
|
354
|
-
);
|
|
355
|
-
|
|
356
|
-
export const setAndGet: {
|
|
357
|
-
<A>(value: A): <E, R>(self: State<A, E, R>) => Effect.Effect<A, E, R>;
|
|
358
|
-
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<A, E, R>;
|
|
359
|
-
} = dual(
|
|
360
|
-
2,
|
|
361
|
-
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<A, E, R> =>
|
|
362
|
-
self.setAndGet(value),
|
|
123
|
+
Semaphore.withPermit(self.semaphore, self.write(value)),
|
|
363
124
|
);
|
|
364
125
|
|
|
126
|
+
/**
|
|
127
|
+
* Updates the value by applying `f` to the current value. The
|
|
128
|
+
* read/apply/write triple is atomic across fibers.
|
|
129
|
+
*/
|
|
365
130
|
export const update: {
|
|
366
131
|
<A>(
|
|
367
132
|
f: (a: A) => A,
|
|
@@ -372,49 +137,88 @@ export const update: {
|
|
|
372
137
|
<A, E, R>(
|
|
373
138
|
self: State<A, E, R>,
|
|
374
139
|
f: (a: A) => A,
|
|
375
|
-
): Effect.Effect<void, E, R> =>
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
381
|
-
): <E, R>(self: State<A, E, R>) => Effect.Effect<void, E | E2, R | R2>;
|
|
382
|
-
<A, E, R, E2, R2>(
|
|
383
|
-
self: State<A, E, R>,
|
|
384
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
385
|
-
): Effect.Effect<void, E | E2, R | R2>;
|
|
386
|
-
} = dual(
|
|
387
|
-
2,
|
|
388
|
-
<A, E, R, E2, R2>(
|
|
389
|
-
self: State<A, E, R>,
|
|
390
|
-
f: (a: A) => Effect.Effect<A, E2, R2>,
|
|
391
|
-
): Effect.Effect<void, E | E2, R | R2> => self.updateEffect(f),
|
|
140
|
+
): Effect.Effect<void, E, R> =>
|
|
141
|
+
Semaphore.withPermit(
|
|
142
|
+
self.semaphore,
|
|
143
|
+
Effect.flatMap(self.read(), (a) => self.write(f(a))),
|
|
144
|
+
),
|
|
392
145
|
);
|
|
393
146
|
|
|
147
|
+
/**
|
|
148
|
+
* Updates the value by applying `f` and returns the new value. The
|
|
149
|
+
* read/apply/write triple is atomic across fibers.
|
|
150
|
+
*/
|
|
394
151
|
export const updateAndGet: {
|
|
395
152
|
<A>(f: (a: A) => A): <E, R>(self: State<A, E, R>) => Effect.Effect<A, E, R>;
|
|
396
153
|
<A, E, R>(self: State<A, E, R>, f: (a: A) => A): Effect.Effect<A, E, R>;
|
|
397
154
|
} = dual(
|
|
398
155
|
2,
|
|
399
156
|
<A, E, R>(self: State<A, E, R>, f: (a: A) => A): Effect.Effect<A, E, R> =>
|
|
400
|
-
|
|
157
|
+
Semaphore.withPermit(
|
|
158
|
+
self.semaphore,
|
|
159
|
+
Effect.flatMap(self.read(), (a) => {
|
|
160
|
+
const next = f(a);
|
|
161
|
+
return Effect.as(self.write(next), next);
|
|
162
|
+
}),
|
|
163
|
+
),
|
|
401
164
|
);
|
|
402
165
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Atomically replaces the value with the second element of `f(prev)`
|
|
168
|
+
* and returns the first. The read/apply/write triple is atomic across
|
|
169
|
+
* fibers.
|
|
170
|
+
*/
|
|
171
|
+
export const modify: {
|
|
172
|
+
<A, B>(
|
|
173
|
+
f: (a: A) => readonly [B, A],
|
|
174
|
+
): <E, R>(self: State<A, E, R>) => Effect.Effect<B, E, R>;
|
|
175
|
+
<A, E, R, B>(
|
|
408
176
|
self: State<A, E, R>,
|
|
409
|
-
f: (a: A) =>
|
|
410
|
-
): Effect.Effect<
|
|
177
|
+
f: (a: A) => readonly [B, A],
|
|
178
|
+
): Effect.Effect<B, E, R>;
|
|
411
179
|
} = dual(
|
|
412
180
|
2,
|
|
413
|
-
<A, E, R,
|
|
181
|
+
<A, E, R, B>(
|
|
414
182
|
self: State<A, E, R>,
|
|
415
|
-
f: (a: A) =>
|
|
416
|
-
): Effect.Effect<
|
|
183
|
+
f: (a: A) => readonly [B, A],
|
|
184
|
+
): Effect.Effect<B, E, R> =>
|
|
185
|
+
Semaphore.withPermit(
|
|
186
|
+
self.semaphore,
|
|
187
|
+
Effect.flatMap(self.read(), (a) => {
|
|
188
|
+
const [b, next] = f(a);
|
|
189
|
+
return Effect.as(self.write(next), b);
|
|
190
|
+
}),
|
|
191
|
+
),
|
|
417
192
|
);
|
|
418
193
|
|
|
194
|
+
/**
|
|
195
|
+
* Stream of every value published to this `State`. New subscribers
|
|
196
|
+
* immediately see the most recent value (replay = 1), then every
|
|
197
|
+
* subsequent publish.
|
|
198
|
+
*/
|
|
419
199
|
export const changes = <A, E, R>(self: State<A, E, R>): Stream.Stream<A> =>
|
|
420
|
-
self.
|
|
200
|
+
Stream.fromPubSub(self.pubsub);
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Publish a value to the change stream as an `Effect`. Does not
|
|
204
|
+
* modify the underlying store.
|
|
205
|
+
*/
|
|
206
|
+
export const publish: {
|
|
207
|
+
<A>(value: A): <E, R>(self: State<A, E, R>) => Effect.Effect<boolean>;
|
|
208
|
+
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<boolean>;
|
|
209
|
+
} = dual(
|
|
210
|
+
2,
|
|
211
|
+
<A, E, R>(self: State<A, E, R>, value: A): Effect.Effect<boolean> =>
|
|
212
|
+
PubSub.publish(self.pubsub, value),
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Synchronous variant of {@link publish}. Returns `true` when the
|
|
217
|
+
* publish succeeded, `false` if the pubsub is shut down. The runtime
|
|
218
|
+
* uses this from rivetkit's `onStateChange` callback to feed the
|
|
219
|
+
* change stream.
|
|
220
|
+
*/
|
|
221
|
+
export const publishUnsafe = <A, E, R>(
|
|
222
|
+
self: State<A, E, R>,
|
|
223
|
+
value: A,
|
|
224
|
+
): boolean => PubSub.publishUnsafe(self.pubsub, value);
|