@rangojs/router 0.4.1 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/types/browser/navigation-client.d.ts +1 -1
  2. package/dist/types/browser/prefetch/cache.d.ts +20 -8
  3. package/dist/types/cache/cf/cf-cache-store.d.ts +19 -8
  4. package/dist/types/cache/cf/cf-cache-types.d.ts +4 -2
  5. package/dist/types/cache/read-through-swr.d.ts +7 -6
  6. package/dist/types/cloudflare/tracing.d.ts +16 -12
  7. package/dist/types/router/instrument.d.ts +45 -15
  8. package/dist/types/router/telemetry-otel.d.ts +4 -4
  9. package/dist/types/router/timeout.d.ts +12 -1
  10. package/dist/types/router/tracing.d.ts +31 -17
  11. package/dist/types/rsc/capture-queue.d.ts +22 -1
  12. package/dist/types/rsc/shell-capture.d.ts +17 -9
  13. package/dist/types/rsc/stream-idle.d.ts +60 -0
  14. package/dist/types/segment-fragments.d.ts +27 -4
  15. package/dist/types/server/request-context.d.ts +28 -9
  16. package/dist/types/vercel/tracing.d.ts +9 -8
  17. package/dist/vite/index.js +1 -1
  18. package/package.json +1 -1
  19. package/skills/cloudflare/SKILL.md +4 -2
  20. package/skills/observability/SKILL.md +33 -4
  21. package/skills/ppr/SKILL.md +25 -9
  22. package/src/browser/navigation-client.ts +77 -27
  23. package/src/browser/prefetch/cache.ts +40 -10
  24. package/src/browser/prefetch/fetch.ts +5 -0
  25. package/src/browser/rsc-router.tsx +12 -6
  26. package/src/cache/cache-runtime.ts +39 -25
  27. package/src/cache/cache-scope.ts +5 -1
  28. package/src/cache/cf/cf-cache-store.ts +423 -90
  29. package/src/cache/cf/cf-cache-types.ts +4 -2
  30. package/src/cache/document-cache.ts +63 -25
  31. package/src/cache/read-through-swr.ts +22 -16
  32. package/src/cloudflare/tracing.ts +16 -12
  33. package/src/router/instrument.ts +61 -15
  34. package/src/router/segment-resolution/loader-cache.ts +12 -1
  35. package/src/router/segment-resolution/revalidation.ts +16 -1
  36. package/src/router/telemetry-otel.ts +4 -4
  37. package/src/router/timeout.ts +12 -1
  38. package/src/router/tracing.ts +37 -17
  39. package/src/rsc/capture-queue.ts +72 -17
  40. package/src/rsc/handler.ts +171 -73
  41. package/src/rsc/rsc-rendering.ts +61 -6
  42. package/src/rsc/shell-capture.ts +83 -31
  43. package/src/rsc/stream-idle.ts +137 -0
  44. package/src/segment-fragments.ts +45 -4
  45. package/src/server/request-context.ts +29 -8
  46. package/src/testing/dispatch.ts +55 -1
  47. package/src/vercel/tracing.ts +9 -8
@@ -45,6 +45,7 @@ import { startHandleCapture, type HandleCapture } from "./handle-capture.js";
45
45
  import { sortedSearchString } from "./cache-key-utils.js";
46
46
  import { encodeKV } from "../encode-kv.js";
47
47
  import { runBackground } from "./background-task.js";
48
+ import { observePhase, PHASES } from "../router/instrument.js";
48
49
  import {
49
50
  normalizeTags,
50
51
  recordRequestTags,
@@ -464,32 +465,45 @@ export function registerCachedFunction<T extends (...args: any[]) => any>(
464
465
  // synchronous kickoff; its async continuations inherit it. The
465
466
  // DERIVED context goes in, so ambient _handleStore reads inside
466
467
  // the body resolve to the isolated store.
467
- const scoped = runWithRequestContext(bgCtx, () =>
468
- runWithCacheTagScope(() => fn.apply(this, args)),
469
- );
470
- const freshResult = await scoped.result;
471
- bgStopCapture?.();
472
- // Merge profile/DSL tags with runtime cacheTag() tags, read after
473
- // awaiting so post-await cacheTag() calls are included. Normalize
474
- // (drops empty profile tags, matching the invalidate path) + dedupe.
475
- const freshTags = [
476
- ...new Set(
477
- normalizeTags([...(profile.tags ?? []), ...scoped.tags]),
468
+ //
469
+ // The span opens inside the request ALS and wraps the WHOLE task —
470
+ // fn kickoff through the store write — so its platform spans nest
471
+ // under rango.background and a slow or failing setItem is part of
472
+ // the traced revalidation, not an untraced tail.
473
+ await runWithRequestContext(bgCtx, () =>
474
+ observePhase(
475
+ PHASES.background("use-cache-revalidation"),
476
+ async () => {
477
+ const scoped = runWithCacheTagScope(() =>
478
+ fn.apply(this, args),
479
+ );
480
+ const freshResult = await scoped.result;
481
+ bgStopCapture?.();
482
+ // Merge profile/DSL tags with runtime cacheTag() tags, read
483
+ // after awaiting so post-await cacheTag() calls are included.
484
+ // Normalize (drops empty profile tags, matching the
485
+ // invalidate path) + dedupe.
486
+ const freshTags = [
487
+ ...new Set(
488
+ normalizeTags([...(profile.tags ?? []), ...scoped.tags]),
489
+ ),
490
+ ];
491
+ recordRequestTags(freshTags, requestCtx);
492
+ const serialized = await serializeResult(freshResult);
493
+ if (serialized !== null) {
494
+ const encodedHandles = bgCapture?.data
495
+ ? await encodeHandles(bgCapture.data)
496
+ : undefined;
497
+ await store.setItem!(cacheKey, serialized, {
498
+ handles: encodedHandles,
499
+ ttl: profile.ttl,
500
+ swr: profile.swr,
501
+ tags: freshTags.length > 0 ? freshTags : undefined,
502
+ });
503
+ }
504
+ },
478
505
  ),
479
- ];
480
- recordRequestTags(freshTags, requestCtx);
481
- const serialized = await serializeResult(freshResult);
482
- if (serialized !== null) {
483
- const encodedHandles = bgCapture?.data
484
- ? await encodeHandles(bgCapture.data)
485
- : undefined;
486
- await store.setItem!(cacheKey, serialized, {
487
- handles: encodedHandles,
488
- ttl: profile.ttl,
489
- swr: profile.swr,
490
- tags: freshTags.length > 0 ? freshTags : undefined,
491
- });
492
- }
506
+ );
493
507
  } catch (bgError) {
494
508
  bgStopCapture?.();
495
509
  // Pass requestCtx explicitly: this runs in a detached background
@@ -401,9 +401,10 @@ export class CacheScope {
401
401
  // flag shares fate with the key: a disrupted ALS already missed the
402
402
  // seeded record and degraded to the full tail.
403
403
  let segments: ResolvedSegment[];
404
+ const ambientContext = _getRequestContext();
404
405
  try {
405
406
  const codec = await import("./segment-codec.js");
406
- segments = _getRequestContext()?._shellFragmentPayload
407
+ segments = ambientContext?._shellFragmentPayload
407
408
  ? await codec.fragmentSegments(cached.segments)
408
409
  : await codec.deserializeSegments(cached.segments);
409
410
  } catch (error) {
@@ -417,6 +418,9 @@ export class CacheScope {
417
418
  .catch((e) =>
418
419
  reportCacheError(e, "cache-delete", `[CacheScope] ${key}: evict`),
419
420
  );
421
+ if (this.isShellImplicitDocScope) {
422
+ ambientContext?._shellImplicitCache?.onCorrupt?.();
423
+ }
420
424
  return { status: "miss" };
421
425
  }
422
426