diff --git a/packages/extension-query/src/internal/MutationRunner.ts b/packages/extension-query/src/internal/MutationRunner.ts index 6a7bace..b5fcb38 100644 --- a/packages/extension-query/src/internal/MutationRunner.ts +++ b/packages/extension-query/src/internal/MutationRunner.ts @@ -35,23 +35,23 @@ export const make = ( const context = yield* Effect.context | EH>() const globalStateRef = yield* SubscriptionRef.make(AsyncData.noData>()) + const queryStateTag = QueryState.makeTag>() + const run = (key: K) => Effect.all([ - QueryClient, - QueryState.makeTag>(), + queryStateTag, + QueryClient.pipe(Effect.flatMap(client => client.ErrorHandler)), ]).pipe( - Effect.flatMap(([client, state]) => client.ErrorHandler.pipe( - Effect.flatMap(errorHandler => state.set(AsyncData.loading()).pipe( - Effect.andThen(mutation(key)), - errorHandler.handle, - Effect.matchCauseEffect({ - onSuccess: v => Effect.succeed(AsyncData.success(v)).pipe( - Effect.tap(state.set) - ), - onFailure: c => Effect.succeed(AsyncData.failure(c)).pipe( - Effect.tap(state.set) - ), - }), - )) + Effect.flatMap(([state, errorHandler]) => state.set(AsyncData.loading()).pipe( + Effect.andThen(mutation(key)), + errorHandler.handle, + Effect.matchCauseEffect({ + onSuccess: v => Effect.succeed(AsyncData.success(v)).pipe( + Effect.tap(state.set) + ), + onFailure: c => Effect.succeed(AsyncData.failure(c)).pipe( + Effect.tap(state.set) + ), + }), )), Effect.provide(context), @@ -60,7 +60,7 @@ export const make = ( const mutate = (...key: K) => run(key).pipe( Effect.provide(QueryState.layer( - QueryState.makeTag>(), + queryStateTag, globalStateRef, value => Ref.set(globalStateRef, value), )) @@ -74,7 +74,7 @@ export const make = ( Effect.tap(() => Queue.shutdown(stateQueue)), Effect.provide(QueryState.layer( - QueryState.makeTag>(), + queryStateTag, stateRef, value => Queue.offer(stateQueue, value).pipe( Effect.andThen(Ref.set(stateRef, value)), diff --git a/packages/extension-query/src/internal/QueryRunner.ts b/packages/extension-query/src/internal/QueryRunner.ts index c0b18c9..8b0d6f9 100644 --- a/packages/extension-query/src/internal/QueryRunner.ts +++ b/packages/extension-query/src/internal/QueryRunner.ts @@ -2,6 +2,8 @@ import { BrowserStream } from "@effect/platform-browser" import * as AsyncData from "@typed/async-data" import { type Cause, type Context, Effect, Fiber, identity, Option, Ref, type Scope, Stream, SubscriptionRef } from "effect" import type * as QueryClient from "../QueryClient.js" +import * as QueryProgress from "../QueryProgress.js" +import * as QueryState from "./QueryState.js" export interface QueryRunner { @@ -43,6 +45,9 @@ export const make = ( const stateRef = yield* SubscriptionRef.make(AsyncData.noData>()) const fiberRef = yield* SubscriptionRef.make(Option.none>()) + const queryStateTag = QueryState.makeTag>() + const queryStateLayer = QueryState.layer(queryStateTag, stateRef, value => Ref.set(stateRef, value)) + const interrupt = fiberRef.pipe( Effect.flatMap(Option.match({ onSome: fiber => Ref.set(fiberRef, Option.none()).pipe( @@ -64,26 +69,31 @@ export const make = ( })) ) - const run = QueryClient.pipe( - Effect.flatMap(client => client.ErrorHandler), - Effect.flatMap(errorHandler => latestKeyRef.pipe( + const run = Effect.all([ + queryStateTag, + QueryClient.pipe(Effect.flatMap(client => client.ErrorHandler)), + ]).pipe( + Effect.flatMap(([state, errorHandler]) => latestKeyRef.pipe( Effect.flatMap(identity), Effect.flatMap(key => query(key).pipe( errorHandler.handle, Effect.matchCauseEffect({ - onSuccess: v => Ref.set(stateRef, AsyncData.success(v)), - onFailure: c => Ref.set(stateRef, AsyncData.failure(c)), + onSuccess: v => state.set(AsyncData.success(v)), + onFailure: c => state.set(AsyncData.failure(c)), }), )), )), Effect.provide(context), + Effect.provide(QueryProgress.QueryProgress.Live), ) - const forkFetch = interrupt.pipe( - Effect.andThen(Ref.set(stateRef, AsyncData.loading()).pipe( - Effect.andThen(run), - Effect.fork, + const forkFetch = queryStateTag.pipe( + Effect.flatMap(state => interrupt.pipe( + Effect.andThen(state.set(AsyncData.loading()).pipe( + Effect.andThen(run), + Effect.fork, + )), )), Effect.flatMap(fiber => @@ -94,18 +104,21 @@ export const make = ( ), Effect.forkDaemon, + Effect.provide(queryStateLayer), ) - const forkRefresh = interrupt.pipe( - Effect.andThen(Ref.update(stateRef, previous => { - if (AsyncData.isSuccess(previous) || AsyncData.isFailure(previous)) - return AsyncData.refreshing(previous) - if (AsyncData.isRefreshing(previous)) - return AsyncData.refreshing(previous.previous) - return AsyncData.loading() - }).pipe( - Effect.andThen(run), - Effect.fork, + const forkRefresh = queryStateTag.pipe( + Effect.flatMap(state => interrupt.pipe( + Effect.andThen(state.update(previous => { + if (AsyncData.isSuccess(previous) || AsyncData.isFailure(previous)) + return AsyncData.refreshing(previous) + if (AsyncData.isRefreshing(previous)) + return AsyncData.refreshing(previous.previous) + return AsyncData.loading() + }).pipe( + Effect.andThen(run), + Effect.fork, + )) )), Effect.flatMap(fiber => @@ -116,6 +129,7 @@ export const make = ( ), Effect.forkDaemon, + Effect.provide(queryStateLayer), ) const fetchOnKeyChange = Effect.addFinalizer(() => interrupt).pipe(