Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 20 additions & 6 deletions reference/resources/resource-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,24 @@ Options (all optional; prefer setting these via `@table` schema directives):

Harper automatically serializes concurrent requests for the same missing or stale record — all waiting requests share a single upstream fetch, preventing cache stampedes.

#### Observing cache disposition

Each `get` on a caching table records whether the record came from the cache or from the source, in the `loadedFromSource` property of both the request context and the `RequestTarget`:

```javascript
const context = {};
const record = await MyCache.get(recordId, context);
console.log(context.loadedFromSource); // true = went to the source, false = served from cache
```

Within a resource method, the same value is available on the active context via `getContext().loadedFromSource` after the `get` resolves. The flag settles as follows:

- `true` — the get went to the source: either it fetched the record, or the source errored and a stale cached record was served as a fallback (`staleIfError`). `true` means a source request was made, not necessarily that the returned data is fresh.
- `false` — the record was served from the cache: fresh hits, `onlyIfCached` requests, stale-while-revalidate responses (the source fetch continues in the background), and requests that waited on another request's in-flight fetch of the same record. This last case means a cache hit can still take as long as an upstream fetch.
- Each get on a caching table in the same context overwrites the value, so read it after the `get` you are measuring.

Note that `get()` returns a plain `RecordObject`, not a resource instance — the record itself does not carry cache disposition; read it from the context (or an explicitly passed `RequestTarget`). Prior to Harper 5.1.16, `context.loadedFromSource` was never assigned and the flag was only observable via an explicitly passed `RequestTarget`.

#### Source `get` — controlling timestamp and expiration

Inside a source `get()` method, the context (`this.getContext()`) exposes caching-specific properties:
Expand Down Expand Up @@ -413,12 +431,6 @@ Post.sourcedFrom(BlogSource);

---

### `wasLoadedFromSource(): boolean`

For caching tables, indicates that this request was a cache miss and the data was loaded from the source resource.

---

### `getUpdatedTime(): number`

Returns the last updated time of the resource (milliseconds since epoch).
Expand Down Expand Up @@ -641,6 +653,7 @@ Returns the current context, which includes:

- `user` — User object with username, role, and authorization information
- `transaction` — The current transaction
- `loadedFromSource` — For caching tables (5.1.16+), cache disposition of the most recent `get` in this context: `true` if it went to the source, `false` if served from cache (see [Observing cache disposition](#observing-cache-disposition))

When triggered by HTTP, the context is the `Request` object with these additional properties:

Expand Down Expand Up @@ -1146,6 +1159,7 @@ getContext is availabe as export from the `harper` module, or as a global variab

- `user` — User object with username, role, and authorization information
- `transaction` — The current transaction
- `loadedFromSource` — For caching tables (5.1.16+), cache disposition of the most recent `get` in this context: `true` if it went to the source, `false` if served from cache (see [Observing cache disposition](#observing-cache-disposition))

When triggered by HTTP, the context is the `Request` object with these additional properties:

Expand Down