toilscript 0.1.52 → 0.1.54

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.
package/dist/web.js CHANGED
@@ -1,8 +1,8 @@
1
- var ASSEMBLYSCRIPT_VERSION = "0.1.52";
1
+ var ASSEMBLYSCRIPT_VERSION = "0.1.54";
2
2
  var ASSEMBLYSCRIPT_IMPORTMAP = {
3
3
  "imports": {
4
- "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.52/dist/toilscript.js",
5
- "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.52/dist/cli.js",
4
+ "toilscript": "https://cdn.jsdelivr.net/npm/toilscript@0.1.54/dist/toilscript.js",
5
+ "toilscript/cli": "https://cdn.jsdelivr.net/npm/toilscript@0.1.54/dist/cli.js",
6
6
  "binaryen": "https://cdn.jsdelivr.net/npm/binaryen@130.0.0-nightly.20260609/index.js",
7
7
  "long": "https://cdn.jsdelivr.net/npm/long@5.3.2/index.js"
8
8
  }
package/package.json CHANGED
@@ -8,7 +8,7 @@
8
8
  "toilscript",
9
9
  "wasm"
10
10
  ],
11
- "version": "0.1.52",
11
+ "version": "0.1.54",
12
12
  "author": "Daniel Wirtz <dcode+assemblyscript@dcode.io>",
13
13
  "license": "Apache-2.0",
14
14
  "homepage": "https://github.com/dacely-cloud/toilscript",
@@ -223,6 +223,10 @@ export namespace toildbHost {
223
223
  @external("env", "data.latest")
224
224
  export declare function latest(handle: u32, keyPtr: usize, keyLen: i32, limit: i32): i32;
225
225
 
226
+ // @ts-ignore: decorator
227
+ @external("env", "data.events_since")
228
+ export declare function eventsSince(handle: u32, keyPtr: usize, keyLen: i32, limit: i32): i32;
229
+
226
230
  // events.append_once -> 1 appended | 0 duplicate (deduped on eventId) | <0 error.
227
231
  // Idempotent append: a retried call with the same eventId never doubles the event.
228
232
  // @ts-ignore: decorator
@@ -451,53 +451,53 @@ export enum MetricId {
451
451
  Status4xx = 5,
452
452
  Status5xx = 6,
453
453
  StaticHits = 7,
454
- WasmDispatches = 8,
455
- ExecutorFullRejects = 9,
456
- UnknownHostRejects = 10,
457
- RateLimitedRejects = 11,
458
- GasUsed = 12,
459
- DbOps = 13,
460
- DbReads = 14,
461
- DbWrites = 15,
462
- DbErrors = 16,
463
- DbLatencyNsSum = 17,
464
- StreamAccepts = 18,
465
- StreamRejectWrongNode = 19,
466
- StreamRejectCapacity = 20,
467
- StreamRejectArtifact = 21,
468
- StreamRejectGuest = 22,
469
- StreamTraps = 23,
470
- StreamIdleTimeouts = 24,
471
- StreamBytesIn = 25,
472
- StreamBytesOut = 26,
473
- StreamBackpressureEvents = 27,
474
- StreamCloses = 28,
475
- StreamDisconnects = 29,
476
- DaemonStarts = 30,
477
- DaemonStartFailures = 31,
478
- DaemonTicksFired = 32,
479
- DaemonTicksSkippedNotLeader = 33,
480
- DaemonTicksFailed = 34,
481
- DaemonLeaderAcquires = 35,
482
- DaemonLeaderFenced = 36,
483
- DaemonHttpCallAttempts = 37,
484
- DaemonHttpCallFailures = 38,
485
- MemGrownBytes = 39,
486
- Emails = 40,
487
- CacheHits = 41,
488
- CacheMisses = 42,
489
- ConnectedStreamsAvg = 43,
490
- ConnectedStreamsPeak = 44,
491
- CommittedMemoryAvg = 45,
492
- CommittedMemoryPeak = 46,
454
+ ExecutorFullRejects = 8,
455
+ UnknownHostRejects = 9,
456
+ RateLimitedRejects = 10,
457
+ GasUsed = 11,
458
+ DbOps = 12,
459
+ DbReads = 13,
460
+ DbWrites = 14,
461
+ DbErrors = 15,
462
+ DbLatencyNsSum = 16,
463
+ StreamAccepts = 17,
464
+ StreamRejectWrongNode = 18,
465
+ StreamRejectCapacity = 19,
466
+ StreamRejectArtifact = 20,
467
+ StreamRejectGuest = 21,
468
+ StreamTraps = 22,
469
+ StreamIdleTimeouts = 23,
470
+ StreamBytesIn = 24,
471
+ StreamBytesOut = 25,
472
+ StreamBackpressureEvents = 26,
473
+ StreamCloses = 27,
474
+ StreamDisconnects = 28,
475
+ DaemonStarts = 29,
476
+ DaemonStartFailures = 30,
477
+ DaemonTicksFired = 31,
478
+ DaemonTicksSkippedNotLeader = 32,
479
+ DaemonTicksFailed = 33,
480
+ DaemonLeaderAcquires = 34,
481
+ DaemonLeaderFenced = 35,
482
+ DaemonHttpCallAttempts = 36,
483
+ DaemonHttpCallFailures = 37,
484
+ MemGrownBytes = 38,
485
+ Emails = 39,
486
+ CacheHits = 40,
487
+ CacheMisses = 41,
488
+ ConnectedStreamsAvg = 42,
489
+ ConnectedStreamsPeak = 43,
490
+ CommittedMemoryAvg = 44,
491
+ CommittedMemoryPeak = 45,
493
492
  }
494
493
 
495
- /// The number of cumulative counter metrics (`MetricId 0..=42`) = the length of the snapshot's lifetime
494
+ /// The number of cumulative counter metrics (`MetricId 0..=41`) = the length of the snapshot's lifetime
496
495
  /// section.
497
- export const METRIC_COUNTERS: i32 = 43;
496
+ export const METRIC_COUNTERS: i32 = 42;
498
497
 
499
- /// A dashboard time range for `Analytics.series`. Short ranges (1h/6h) read the per-MINUTE ring; the rest
500
- /// read the per-HOUR ring (30-day retention).
498
+ /// A dashboard time range for `Analytics.series`. Short ranges (1h/6h) read the per-MINUTE ring; the long
499
+ /// ranges (60d/90d) read the per-DAY ring (90-day retention); the rest read the per-HOUR ring (30-day).
500
+ /// Append-only: never renumber (D60/D90 were added after D30, keeping the wire ids stable).
501
501
  export enum AnalyticsRange {
502
502
  H1 = 0,
503
503
  H6 = 1,
@@ -507,6 +507,8 @@ export enum AnalyticsRange {
507
507
  D7 = 5,
508
508
  D14 = 6,
509
509
  D30 = 7,
510
+ D60 = 8,
511
+ D90 = 9,
510
512
  }
511
513
 
512
514
  /// One tenant's analytics snapshot: the lifetime totals (indexed by `MetricId`, NO string keys), the two
@@ -523,6 +525,16 @@ export class TenantStats {
523
525
  reqMinuteCap: u64 = 0;
524
526
  reqDayUsed: u64 = 0;
525
527
  reqDayCap: u64 = 0;
528
+ /// LIVE per-second gauges (rates), computed edge-side from the last completed minute bucket so the
529
+ /// guest is STATELESS (no client diffing of two snapshots). Idle -> 0.0. `f64` (a rate is fractional
530
+ /// and bounded; f64 cannot overflow for any real value).
531
+ rps: f64 = 0;
532
+ bytesInPerSec: f64 = 0;
533
+ bytesOutPerSec: f64 = 0;
534
+ streamBytesInPerSec: f64 = 0;
535
+ streamBytesOutPerSec: f64 = 0;
536
+ dbOpsPerSec: f64 = 0;
537
+ gasPerSec: f64 = 0;
526
538
  /// Edge wall-clock (ms) when the snapshot was read.
527
539
  nowMs: u64 = 0;
528
540
 
@@ -540,7 +552,6 @@ export class TenantStats {
540
552
  get status4xx(): u64 { return this.life[MetricId.Status4xx]; }
541
553
  get status5xx(): u64 { return this.life[MetricId.Status5xx]; }
542
554
  get staticHits(): u64 { return this.life[MetricId.StaticHits]; }
543
- get wasmDispatches(): u64 { return this.life[MetricId.WasmDispatches]; }
544
555
  get executorFullRejects(): u64 { return this.life[MetricId.ExecutorFullRejects]; }
545
556
  get unknownHostRejects(): u64 { return this.life[MetricId.UnknownHostRejects]; }
546
557
  get rateLimitedRejects(): u64 { return this.life[MetricId.RateLimitedRejects]; }
@@ -591,19 +602,28 @@ export class TenantStats {
591
602
  }
592
603
  }
593
604
 
594
- /// One metric's time series for a range: `points` oldest→newest, `bucketSecs` the per-bucket width, and
595
- /// `headMs` the newest bucket's end. Rates are derived, never stored.
605
+ /// One metric's time series for a range: `points` oldest→newest (per-bucket totals, `u64` — non-negative),
606
+ /// `bucketSecs` the per-bucket width, and `headMs` the newest bucket's end. Rates are derived, never stored.
596
607
  export class Series {
597
608
  metric: MetricId = MetricId.Requests;
598
609
  bucketSecs: u32 = 0;
599
610
  headMs: u64 = 0;
600
- points: i64[] = [];
611
+ points: u64[] = [];
601
612
 
602
613
  /// Per-second rate of bucket `i` (its total divided by the bucket width). 0 for an out-of-range index.
603
614
  ratePerSec(i: i32): f64 {
604
615
  if (i < 0 || i >= this.points.length || this.bucketSecs == 0) return 0;
605
616
  return <f64>this.points[i] / <f64>this.bucketSecs;
606
617
  }
618
+
619
+ /// The CUMULATIVE total over the whole window (e.g. total bytes across a 30d/90d range). Folded into an
620
+ /// `f64` accumulator — NEVER a `u64`/`i64` sum, which could overflow a long byte-count window (AS has no
621
+ /// u128; `f64` max is 1.8e308, so it cannot overflow for any real value).
622
+ sum(): f64 {
623
+ let acc: f64 = 0;
624
+ for (let i = 0; i < this.points.length; i++) acc += <f64>this.points[i];
625
+ return acc;
626
+ }
607
627
  }
608
628
 
609
629
  /// A page of site names from `Analytics.listSites` (dacely.com only). When `hasMore` is
@@ -636,6 +656,16 @@ export class Analytics {
636
656
  stats.reqMinuteCap = r.readU64();
637
657
  stats.reqDayUsed = r.readU64();
638
658
  stats.reqDayCap = r.readU64();
659
+ // LIVE per-second rates (f64), appended after the windows. VERSION-GATE by LENGTH: a pre-rates
660
+ // (shorter) frame from an older edge exhausts the buffer here, so `readF64` returns 0.0 for each
661
+ // missing rate (DataReader is bounds-checked). No frame-version bump needed.
662
+ stats.rps = r.readF64();
663
+ stats.bytesInPerSec = r.readF64();
664
+ stats.bytesOutPerSec = r.readF64();
665
+ stats.streamBytesInPerSec = r.readF64();
666
+ stats.streamBytesOutPerSec = r.readF64();
667
+ stats.dbOpsPerSec = r.readF64();
668
+ stats.gasPerSec = r.readF64();
639
669
  return stats;
640
670
  }
641
671
 
@@ -648,8 +678,9 @@ export class Analytics {
648
678
  out.bucketSecs = r.readU32();
649
679
  out.headMs = r.readU64();
650
680
  const count = <i32>r.readU32();
651
- const pts = new Array<i64>(count);
652
- for (let i: i32 = 0; i < count && r.ok; i++) pts[i] = r.readI64();
681
+ // Points are non-negative per-bucket totals: read as u64 (matches the edge `u64 LE` series frame).
682
+ const pts = new Array<u64>(count);
683
+ for (let i: i32 = 0; i < count && r.ok; i++) pts[i] = r.readU64();
653
684
  out.points = pts;
654
685
  return out;
655
686
  }
@@ -735,6 +766,34 @@ export class Events<K, V> {
735
766
  return status == 1;
736
767
  }
737
768
 
769
+ /// The NEXT batch of events for `key` past this derive's checkpoint, OLDEST first, up to `limit`. The
770
+ /// host owns the resumable cursor (seeded from the durable checkpoint and advanced/committed around the
771
+ /// fold), so repeated calls drain an unbounded log in bounded batches and return an empty array once
772
+ /// caught up. Use it in a `@derive` (or `@job`) to fold a growing log incrementally instead of rescanning:
773
+ /// `for (const e of this.events.since(key, 500)) { ...update the view... }`, looping until it is empty.
774
+ /// The fold must be idempotent per event (a heal can trigger a full re-read). Same frame as `latest`.
775
+ since(key: K, limit: i32): V[] {
776
+ const kb = key.encode();
777
+ const status = toildbHost.eventsSince(this.__handle, kb.dataStart, kb.byteLength, limit);
778
+ if (status < 0) unreachable();
779
+ const blob = __toildbTake(status);
780
+ const out = new Array<V>();
781
+ let off: i32 = 0;
782
+ const count = load<u32>(blob.dataStart + off);
783
+ off += 4;
784
+ for (let i: u32 = 0; i < count; i++) {
785
+ const ver = <i64>load<u32>(blob.dataStart + off);
786
+ off += 4;
787
+ const len = <i32>load<u32>(blob.dataStart + off);
788
+ off += 4;
789
+ const ev = instantiate<V>();
790
+ ev.decodeIntoVersioned(blob.subarray(off, off + len), ver);
791
+ out.push(ev);
792
+ off += len;
793
+ }
794
+ return out;
795
+ }
796
+
738
797
  /// The newest `limit` events, newest first. Decodes each framed event into a
739
798
  /// `V`. The host frames them as `u32 count` then per event
740
799
  /// `u32 schema_version + u32 len + bytes`.
@@ -280,29 +280,31 @@ declare class Counter<K> {
280
280
  declare class Events<K, V> {
281
281
  append(key: K, event: V): void;
282
282
  latest(key: K, limit: i32): V[];
283
+ since(key: K, limit: i32): V[];
283
284
  }
284
285
 
285
286
  /** Every per-domain metric, by stable numeric id (the wire contract). `0..=42` are cumulative
286
- * COUNTERS (rate = value/seconds); `43..=46` are the avg/peak series of the two GAUGES. */
287
+ * COUNTERS (rate = value/seconds); `42..=45` are the avg/peak series of the two GAUGES. */
287
288
  declare const enum MetricId {
288
289
  Requests = 0, BytesOutL1 = 1, BytesInL1 = 2,
289
290
  Status2xx = 3, Status3xx = 4, Status4xx = 5, Status5xx = 6,
290
- StaticHits = 7, WasmDispatches = 8,
291
- ExecutorFullRejects = 9, UnknownHostRejects = 10, RateLimitedRejects = 11, GasUsed = 12,
292
- DbOps = 13, DbReads = 14, DbWrites = 15, DbErrors = 16, DbLatencyNsSum = 17,
293
- StreamAccepts = 18, StreamRejectWrongNode = 19, StreamRejectCapacity = 20, StreamRejectArtifact = 21,
294
- StreamRejectGuest = 22, StreamTraps = 23, StreamIdleTimeouts = 24, StreamBytesIn = 25,
295
- StreamBytesOut = 26, StreamBackpressureEvents = 27, StreamCloses = 28, StreamDisconnects = 29,
296
- DaemonStarts = 30, DaemonStartFailures = 31, DaemonTicksFired = 32, DaemonTicksSkippedNotLeader = 33,
297
- DaemonTicksFailed = 34, DaemonLeaderAcquires = 35, DaemonLeaderFenced = 36,
298
- DaemonHttpCallAttempts = 37, DaemonHttpCallFailures = 38, MemGrownBytes = 39, Emails = 40,
299
- CacheHits = 41, CacheMisses = 42,
300
- ConnectedStreamsAvg = 43, ConnectedStreamsPeak = 44, CommittedMemoryAvg = 45, CommittedMemoryPeak = 46,
291
+ StaticHits = 7,
292
+ ExecutorFullRejects = 8, UnknownHostRejects = 9, RateLimitedRejects = 10, GasUsed = 11,
293
+ DbOps = 12, DbReads = 13, DbWrites = 14, DbErrors = 15, DbLatencyNsSum = 16,
294
+ StreamAccepts = 17, StreamRejectWrongNode = 18, StreamRejectCapacity = 19, StreamRejectArtifact = 20,
295
+ StreamRejectGuest = 21, StreamTraps = 22, StreamIdleTimeouts = 23, StreamBytesIn = 24,
296
+ StreamBytesOut = 25, StreamBackpressureEvents = 26, StreamCloses = 27, StreamDisconnects = 28,
297
+ DaemonStarts = 29, DaemonStartFailures = 30, DaemonTicksFired = 31, DaemonTicksSkippedNotLeader = 32,
298
+ DaemonTicksFailed = 33, DaemonLeaderAcquires = 34, DaemonLeaderFenced = 35,
299
+ DaemonHttpCallAttempts = 36, DaemonHttpCallFailures = 37, MemGrownBytes = 38, Emails = 39,
300
+ CacheHits = 40, CacheMisses = 41,
301
+ ConnectedStreamsAvg = 42, ConnectedStreamsPeak = 43, CommittedMemoryAvg = 44, CommittedMemoryPeak = 45,
301
302
  }
302
303
 
303
- /** A dashboard time range for `Analytics.series`. 1h/6h are per-minute; the rest per-hour (30-day). */
304
+ /** A dashboard time range for `Analytics.series`. 1h/6h are per-minute; 60d/90d are per-day (90-day
305
+ * retention); the rest are per-hour (30-day). Append-only ids. */
304
306
  declare const enum AnalyticsRange {
305
- H1 = 0, H6 = 1, H12 = 2, H24 = 3, D3 = 4, D7 = 5, D14 = 6, D30 = 7,
307
+ H1 = 0, H6 = 1, H12 = 2, H24 = 3, D3 = 4, D7 = 5, D14 = 6, D30 = 7, D60 = 8, D90 = 9,
306
308
  }
307
309
 
308
310
  /** One tenant's analytics snapshot: lifetime totals (indexed by `MetricId`, no string keys), the two
@@ -318,7 +320,6 @@ declare class TenantStats {
318
320
  readonly status4xx: u64;
319
321
  readonly status5xx: u64;
320
322
  readonly staticHits: u64;
321
- readonly wasmDispatches: u64;
322
323
  readonly executorFullRejects: u64;
323
324
  readonly unknownHostRejects: u64;
324
325
  readonly rateLimitedRejects: u64;
@@ -362,17 +363,28 @@ declare class TenantStats {
362
363
  reqMinuteCap: u64;
363
364
  reqDayUsed: u64;
364
365
  reqDayCap: u64;
366
+ /** LIVE per-second gauges (rates), computed edge-side from the last completed minute bucket (idle 0.0),
367
+ * so no client diffing is needed. `f64` cannot overflow for any real value. */
368
+ readonly rps: f64;
369
+ readonly bytesInPerSec: f64;
370
+ readonly bytesOutPerSec: f64;
371
+ readonly streamBytesInPerSec: f64;
372
+ readonly streamBytesOutPerSec: f64;
373
+ readonly dbOpsPerSec: f64;
374
+ readonly gasPerSec: f64;
365
375
  nowMs: u64;
366
376
  }
367
377
 
368
- /** One metric's time series for a range: `points` oldest→newest, `bucketSecs` bucket width,
369
- * `headMs` newest bucket end. `ratePerSec(i)` derives the per-second rate of point `i`. */
378
+ /** One metric's time series for a range: `points` oldest→newest (per-bucket totals, `u64`), `bucketSecs`
379
+ * bucket width, `headMs` newest bucket end. `ratePerSec(i)` derives the per-second rate of point `i`;
380
+ * `sum()` folds the window into an `f64` cumulative (never a `u64` sum -> overflow-safe). */
370
381
  declare class Series {
371
382
  metric: MetricId;
372
383
  bucketSecs: u32;
373
384
  headMs: u64;
374
- points: i64[];
385
+ points: u64[];
375
386
  ratePerSec(i: i32): f64;
387
+ sum(): f64;
376
388
  }
377
389
 
378
390
  /** A page of site names from `Analytics.listSites` (dacely.com only). When `hasMore` is