Fix
Lint / lint (push) Failing after 42s

This commit is contained in:
Julien Valverdé
2026-07-23 04:13:27 +02:00
parent d8b9c0394c
commit 296f65ee1b
3 changed files with 54 additions and 2 deletions
+10
View File
@@ -153,12 +153,20 @@ export interface ComponentOptions {
* @default "100 millis" * @default "100 millis"
*/ */
readonly finalizerExecutionDebounce: Duration.Input readonly finalizerExecutionDebounce: Duration.Input
/**
* Maximum duration an uncommitted scope may remain registered before it is considered abandoned.
*
* @default "30 seconds"
*/
readonly scopeCommitTimeout: Duration.Input
} }
export const defaultOptions: ComponentOptions = { export const defaultOptions: ComponentOptions = {
nonReactiveTags: [Tracer.ParentSpan, Scheduler.Scheduler, Layer.CurrentMemoMap], nonReactiveTags: [Tracer.ParentSpan, Scheduler.Scheduler, Layer.CurrentMemoMap],
finalizerExecutionStrategy: "sequential", finalizerExecutionStrategy: "sequential",
finalizerExecutionDebounce: "100 millis", finalizerExecutionDebounce: "100 millis",
scopeCommitTimeout: "1 minute",
} }
@@ -641,6 +649,7 @@ export declare namespace useScope {
export interface Options { export interface Options {
readonly finalizerExecutionStrategy?: "sequential" | "parallel" readonly finalizerExecutionStrategy?: "sequential" | "parallel"
readonly finalizerExecutionDebounce?: Duration.Input readonly finalizerExecutionDebounce?: Duration.Input
readonly scopeCommitTimeout?: Duration.Input
} }
} }
@@ -675,6 +684,7 @@ export const useScope = Effect.fnUntraced(function*(
const entry = yield* registry.register(key, { const entry = yield* registry.register(key, {
finalizerExecutionStrategy: options?.finalizerExecutionStrategy ?? defaultOptions.finalizerExecutionStrategy, finalizerExecutionStrategy: options?.finalizerExecutionStrategy ?? defaultOptions.finalizerExecutionStrategy,
finalizerExecutionDebounce: options?.finalizerExecutionDebounce ?? defaultOptions.finalizerExecutionDebounce, finalizerExecutionDebounce: options?.finalizerExecutionDebounce ?? defaultOptions.finalizerExecutionDebounce,
scopeCommitTimeout: options?.scopeCommitTimeout ?? defaultOptions.scopeCommitTimeout,
}) })
return [key, entry.scope] return [key, entry.scope]
+2 -1
View File
@@ -20,6 +20,7 @@ export declare namespace ScopeRegistryService {
export interface RegisterOptions { export interface RegisterOptions {
readonly finalizerExecutionStrategy: "sequential" | "parallel" readonly finalizerExecutionStrategy: "sequential" | "parallel"
readonly finalizerExecutionDebounce: Duration.Input readonly finalizerExecutionDebounce: Duration.Input
readonly scopeCommitTimeout: Duration.Input
} }
export interface Entry { export interface Entry {
@@ -45,7 +46,7 @@ export class ScopeRegistryServiceImpl implements ScopeRegistryService {
return Effect.gen({ self: this }, function*() { return Effect.gen({ self: this }, function*() {
const entry = Equal.byReference({ const entry = Equal.byReference({
scope: yield* Scope.make(options.finalizerExecutionStrategy), scope: yield* Scope.make(options.finalizerExecutionStrategy),
expiresAt: Option.some(DateTime.addDuration(yield* DateTime.now, options.finalizerExecutionDebounce)), expiresAt: Option.some(DateTime.addDuration(yield* DateTime.now, options.scopeCommitTimeout)),
finalizerExecutionDebounce: options.finalizerExecutionDebounce, finalizerExecutionDebounce: options.finalizerExecutionDebounce,
}) })
@@ -374,6 +374,7 @@ describe("Component", () => {
React.use(pending) React.use(pending)
return <div>committed</div> return <div>committed</div>
}).pipe( }).pipe(
Component.withOptions({ scopeCommitTimeout: "10 millis" }),
Component.withContext(runtime.context) Component.withContext(runtime.context)
) )
@@ -414,7 +415,10 @@ describe("Component", () => {
return <div>committed</div> return <div>committed</div>
}).pipe( }).pipe(
Component.withOptions({ finalizerExecutionDebounce: "10 millis" }), Component.withOptions({
finalizerExecutionDebounce: "10 millis",
scopeCommitTimeout: "10 millis",
}),
Component.withContext(runtime.context), Component.withContext(runtime.context),
) )
@@ -437,6 +441,42 @@ describe("Component", () => {
await runtime.runtime.dispose() await runtime.runtime.dispose()
}) })
it("does not expire a scope while a descendant is suspended past the finalizer debounce", async () => {
const runtime = ReactRuntime.make(Layer.empty)
let resolve!: () => void
const pending = new Promise<void>(complete => {
resolve = complete
})
const Suspended = () => {
React.use(pending)
return <div>committed</div>
}
let view!: ReturnType<typeof render>
await act(async () => {
view = render(
<ReactRuntime.Provider runtime={runtime} fallback={<div>fallback</div>}>
<Suspended />
</ReactRuntime.Provider>
)
})
try {
await screen.findByText("fallback")
await new Promise(resolve => setTimeout(resolve, 150))
await act(async () => {
resolve()
await pending
})
await screen.findByText("committed")
}
finally {
view.unmount()
await runtime.runtime.dispose()
}
})
it("clears ScopeRegistry after a suspended render retries, commits, and unmounts", async () => { it("clears ScopeRegistry after a suspended render retries, commits, and unmounts", async () => {
const lifecycle = vi.fn<(message: string) => void>() const lifecycle = vi.fn<(message: string) => void>()
const runtime = ReactRuntime.make(Layer.empty) const runtime = ReactRuntime.make(Layer.empty)
@@ -455,6 +495,7 @@ describe("Component", () => {
}), []) }), [])
return <div>committed</div> return <div>committed</div>
}).pipe( }).pipe(
Component.withOptions({ scopeCommitTimeout: "10 millis" }),
Component.withContext(runtime.context) Component.withContext(runtime.context)
) )