fix(core): batch plugin shutdown
This commit is contained in:
parent
79b55d4db8
commit
cf31029350
2 changed files with 45 additions and 3 deletions
|
|
@ -103,8 +103,16 @@ export const layer = Layer.effect(
|
||||||
}
|
}
|
||||||
}[keyof Hooks][] = []
|
}[keyof Hooks][] = []
|
||||||
const events = yield* EventV2.Service
|
const events = yield* EventV2.Service
|
||||||
const scope = yield* Scope.Scope
|
|
||||||
const locks = KeyedMutex.makeUnsafe<ID>()
|
const locks = KeyedMutex.makeUnsafe<ID>()
|
||||||
|
const scope = yield* Scope.make()
|
||||||
|
|
||||||
|
// One registry-owned scope lets shutdown remove every plugin transform in one batch.
|
||||||
|
yield* Effect.addFinalizer((exit) =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
hooks = []
|
||||||
|
yield* State.batch(Scope.close(scope, exit))
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
const svc = Service.of({
|
const svc = Service.of({
|
||||||
add: Effect.fn("Plugin.add")(function* (input) {
|
add: Effect.fn("Plugin.add")(function* (input) {
|
||||||
|
|
@ -112,7 +120,7 @@ export const layer = Layer.effect(
|
||||||
yield* locks.withLock(id)(
|
yield* locks.withLock(id)(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const existing = hooks.find((item) => item.id === id)
|
const existing = hooks.find((item) => item.id === id)
|
||||||
if (existing) yield* Scope.close(existing.scope, Exit.void).pipe(Effect.ignore)
|
if (existing) yield* State.batch(Scope.close(existing.scope, Exit.void)).pipe(Effect.ignore)
|
||||||
const childScope = yield* Scope.fork(scope)
|
const childScope = yield* Scope.fork(scope)
|
||||||
const result = yield* input.effect.pipe(
|
const result = yield* input.effect.pipe(
|
||||||
Scope.provide(childScope),
|
Scope.provide(childScope),
|
||||||
|
|
@ -181,7 +189,7 @@ export const layer = Layer.effect(
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const existing = hooks.find((item) => item.id === id)
|
const existing = hooks.find((item) => item.id === id)
|
||||||
hooks = hooks.filter((item) => item.id !== id)
|
hooks = hooks.filter((item) => item.id !== id)
|
||||||
if (existing) yield* Scope.close(existing.scope, Exit.void).pipe(Effect.ignore)
|
if (existing) yield* State.batch(Scope.close(existing.scope, Exit.void)).pipe(Effect.ignore)
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
}),
|
}),
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,40 @@ describe("PluginV2", () => {
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
it.effect("batches plugin state rebuilds when the registry layer finalizes", () =>
|
||||||
|
Effect.gen(function* () {
|
||||||
|
let finalized = 0
|
||||||
|
const values = State.create({
|
||||||
|
initial: () => ({ values: [] as string[] }),
|
||||||
|
draft: (draft) => ({ add: (value: string) => draft.values.push(value) }),
|
||||||
|
finalize: () => Effect.sync(() => finalized++),
|
||||||
|
})
|
||||||
|
const layerScope = yield* Scope.fork(yield* Scope.Scope)
|
||||||
|
const plugin = Context.get(yield* Layer.buildWithScope(Layer.fresh(plugins), layerScope), PluginV2.Service)
|
||||||
|
|
||||||
|
yield* State.batch(
|
||||||
|
Effect.forEach(
|
||||||
|
["first", "second"],
|
||||||
|
(id) =>
|
||||||
|
plugin.add({
|
||||||
|
id: PluginV2.ID.make(id),
|
||||||
|
effect: values
|
||||||
|
.transform((editor) => {
|
||||||
|
editor.add(id)
|
||||||
|
})
|
||||||
|
.pipe(Effect.asVoid),
|
||||||
|
}),
|
||||||
|
{ discard: true },
|
||||||
|
),
|
||||||
|
)
|
||||||
|
finalized = 0
|
||||||
|
|
||||||
|
yield* Scope.close(layerScope, Exit.void)
|
||||||
|
expect(values.get().values).toEqual([])
|
||||||
|
expect(finalized).toBe(1)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
|
||||||
it.effect("serializes same-ID additions and leaves one removable attachment", () =>
|
it.effect("serializes same-ID additions and leaves one removable attachment", () =>
|
||||||
Effect.gen(function* () {
|
Effect.gen(function* () {
|
||||||
const values = state()
|
const values = state()
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue