Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 214b500623 |
@@ -40,13 +40,6 @@ jobs:
|
||||
access: public
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
registry: https://registry.npmjs.org
|
||||
- name: Publish @effect-view/vite-plugin
|
||||
uses: JS-DevTools/npm-publish@v4
|
||||
with:
|
||||
package: packages/vite-plugin
|
||||
access: public
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
registry: https://registry.npmjs.org
|
||||
- name: Publish effect-fc
|
||||
uses: JS-DevTools/npm-publish@v4
|
||||
with:
|
||||
|
||||
@@ -12,7 +12,7 @@ jobs:
|
||||
- name: Setup Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: "22"
|
||||
node-version: "24"
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
FROM oven/bun:1.3.12-debian@sha256:1b709c9dd883fc1af38c210f7ea5222c552a8d470ea73efbd4b8fcfee798a64b AS bun
|
||||
|
||||
FROM node:22.21.1-trixie-slim@sha256:98e1429d1a0b99378b4de43fa385f0746fd6276faf4feeb6104d91f6bad290f9
|
||||
FROM node:24.18.0-trixie-slim@sha256:ae91dcc111a68c9d2d81ff2a17bda61be126426176fde6fe7d08ab13b7f50573
|
||||
COPY --from=bun /usr/local/bin/bun /usr/local/bin/bunx /usr/local/bin/
|
||||
COPY . /app
|
||||
WORKDIR /app
|
||||
|
||||
@@ -248,33 +248,6 @@ workflows that need to wait for the final success or failure state.
|
||||
Invalidating does not itself refetch. Follow it with `refreshView`, change the
|
||||
key, or allow a later fetch to repopulate the cache.
|
||||
|
||||
### Refresh on an interval
|
||||
|
||||
Refresh every five minutes, starting after five minutes:
|
||||
|
||||
```ts
|
||||
import { Schedule } from "effect"
|
||||
|
||||
yield* query.pipe(
|
||||
Query.withScheduledRefresh(Schedule.spaced("5 minutes")),
|
||||
)
|
||||
```
|
||||
|
||||
Limit the number of refreshes:
|
||||
|
||||
```ts
|
||||
yield* query.pipe(
|
||||
Query.withScheduledRefresh(
|
||||
Schedule.spaced("5 minutes").pipe(
|
||||
Schedule.upTo({ times: 3 }),
|
||||
),
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
The refresh fiber stops with the surrounding scope. The Effect returns the
|
||||
original query. Cache and `staleTime` rules still apply.
|
||||
|
||||
## Staleness and cache lifetime
|
||||
|
||||
`staleTime` controls how long a successful result can satisfy a fetch without
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"@docusaurus/types": "^3.10.2",
|
||||
"@types/react": "^19.2.15",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"typescript": "~7.0.0"
|
||||
"typescript": "~6.0.3"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Effect, Schedule, type Scope, Stream } from "effect"
|
||||
import { TestClock } from "effect/testing"
|
||||
import { Effect, type Scope, Stream } from "effect"
|
||||
import { AsyncResult } from "effect/unstable/reactivity"
|
||||
import { describe, expect, it } from "vitest"
|
||||
import * as Query from "./Query.js"
|
||||
@@ -80,49 +79,6 @@ describe("Query", () => {
|
||||
expect(expectSuccessValue(result[1])).toBe("value:1:2")
|
||||
})
|
||||
|
||||
it("withScheduledRefresh lets the Schedule control the first refresh", async () => {
|
||||
let calls = 0
|
||||
const key = staticKey<readonly [number]>([1])
|
||||
|
||||
const result = await runQueryTest(Effect.gen(function*() {
|
||||
const query = yield* Query.make({
|
||||
key,
|
||||
f: () => Effect.sync(() => {
|
||||
calls += 1
|
||||
return calls
|
||||
}),
|
||||
staleTime: "0 millis",
|
||||
})
|
||||
|
||||
yield* query.fetch([1])
|
||||
const returnedQuery = yield* query.pipe(Query.withScheduledRefresh(
|
||||
Schedule.spaced("1 second").pipe(
|
||||
Schedule.upTo({ times: 1 }),
|
||||
),
|
||||
))
|
||||
|
||||
yield* TestClock.adjust("999 millis")
|
||||
const beforeInterval = calls
|
||||
|
||||
yield* TestClock.adjust("1 millis")
|
||||
const afterFirstInterval = calls
|
||||
|
||||
return {
|
||||
returnsQuery: returnedQuery === query,
|
||||
beforeInterval,
|
||||
afterFirstInterval,
|
||||
}
|
||||
}).pipe(
|
||||
Effect.provide(TestClock.layer()),
|
||||
))
|
||||
|
||||
expect(result).toEqual({
|
||||
returnsQuery: true,
|
||||
beforeInterval: 1,
|
||||
afterFirstInterval: 2,
|
||||
})
|
||||
})
|
||||
|
||||
it("invalidateCacheEntry forces the next fetch for that key to rerun", async () => {
|
||||
let calls = 0
|
||||
const key = staticKey<readonly [number]>([1])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Cause, type Context, Duration, Effect, Equal, type Equivalence, Exit, Fiber, Function, Option, Pipeable, Predicate, PubSub, Ref, type Schedule, type Scope, Semaphore, Stream, SubscriptionRef } from "effect"
|
||||
import { Cause, type Context, Duration, Effect, Equal, type Equivalence, Exit, Fiber, Option, Pipeable, Predicate, PubSub, Ref, type Scope, Semaphore, Stream, SubscriptionRef } from "effect"
|
||||
import { AsyncResult } from "effect/unstable/reactivity"
|
||||
import * as Lens from "./Lens.js"
|
||||
import * as QueryClient from "./QueryClient.js"
|
||||
@@ -421,43 +421,6 @@ export const service = <K, A, E = never, R = never>(
|
||||
query => Effect.forkScoped(query.run),
|
||||
)
|
||||
|
||||
/**
|
||||
* Refreshes the Query on a schedule and returns it.
|
||||
*
|
||||
* @example Refresh every five minutes, starting after five minutes
|
||||
* ```ts
|
||||
* yield* query.pipe(
|
||||
* Query.withScheduledRefresh(Schedule.spaced("5 minutes")),
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* @example Refresh at most three times
|
||||
* ```ts
|
||||
* yield* query.pipe(
|
||||
* Query.withScheduledRefresh(
|
||||
* Schedule.spaced("5 minutes").pipe(Schedule.upTo({ times: 3 })),
|
||||
* ),
|
||||
* )
|
||||
* ```
|
||||
*/
|
||||
export const withScheduledRefresh: {
|
||||
<Output, Error, Env>(
|
||||
schedule: Schedule.Schedule<Output, unknown, Error, Env>,
|
||||
): <K, A, E, R>(
|
||||
self: Query<K, A, E, R>,
|
||||
) => Effect.Effect<Query<K, A, E, R>, never, Scope.Scope | Env>
|
||||
<K, A, E, R, Output, Error, Env>(
|
||||
self: Query<K, A, E, R>,
|
||||
schedule: Schedule.Schedule<Output, unknown, Error, Env>,
|
||||
): Effect.Effect<Query<K, A, E, R>, never, Scope.Scope | Env>
|
||||
} = Function.dual(2, <K, A, E, R, Output, Error, Env>(
|
||||
self: Query<K, A, E, R>,
|
||||
schedule: Schedule.Schedule<Output, unknown, Error, Env>,
|
||||
) => Effect.schedule(self.refresh, schedule).pipe(
|
||||
Effect.forkScoped,
|
||||
Effect.as(self),
|
||||
))
|
||||
|
||||
|
||||
export class QueryStateLens<in out K, in out A, in out E = never>
|
||||
extends Lens.LensImpl<QueryState<K, A, E>, never, never, never, never> {
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
"clean:modules": "rm -rf node_modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"typescript": "^7.0.0"
|
||||
"typescript": "^6.0.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"effect-view": "workspace:*",
|
||||
|
||||
Reference in New Issue
Block a user