solid-objects 0.14.2 → 0.14.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,84 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.4 - 2026-08-29
4
+
5
+ - Cut the per-turn state traversals from eight to four. The runtime built the
6
+ whole state image eight times for each committed operation, and nine times
7
+ for a query, where two are necessary. The commit path now passes the image it
8
+ already holds to the observables guard, and the query check reads the
9
+ committed image instead of taking its own. The guard is unchanged: it still
10
+ reads the state after `observables()` returns, because only that read sees a
11
+ mutation.
12
+ - Compute the default state once for each registered actor class. Every `send`
13
+ and every hydration constructed a throwaway actor and serialized its full
14
+ default state. The constructor must not depend on external state, so one
15
+ cached image per validated definition is correct. Each caller receives a
16
+ detached copy.
17
+ - Stop building a string that `normalizeJson` discards. It called
18
+ `JSON.stringify` on every value, then used the result only when a byte limit
19
+ was given. `actorState`, `deepCopy`, and `stableJson` all pass no limit.
20
+ - Measured on an Apple M5 with SQLite: 1.2x throughput at 0 KB of state, 1.3x
21
+ at 16 KB, 1.6x at 128 KB, and 2.1x at 1 MB. See
22
+ [Large state](docs/benchmarks.md#large-state).
23
+ - Add `warnStateBytes`, a soft threshold that defaults to 128 KB. A commit
24
+ above it reports one `solid_objects.state.large` instrumentation event with
25
+ the actor type, the actor ID, the byte count, and the threshold. The runtime
26
+ reports it only after the commit succeeds, so a turn that rolls back stays
27
+ silent. The event holds no application state, and the runtime measures the
28
+ size only when an `instrumentation` callback is configured. `maxStateBytes` keeps its 5 MB hard
29
+ default, which fails the turn. Throughput at that size is about one operation
30
+ per second, so the warning names the constraint before an application meets
31
+ it.
32
+ - Add a `large-state` benchmark scenario, `pnpm run benchmark:large-state`,
33
+ that reports operations per second at 0 KB, 16 KB, 128 KB, and 1 MB, and
34
+ document the measured curve in `docs/state-and-lifecycle.md`.
35
+
36
+ - Align the use-case claims with the Ruby gem. The README table sold per-key
37
+ rate limits, while the Ruby fit guide called a rate limiter an anti-pattern.
38
+ Both projects now draw one line: a low-rate quota that a reminder refills
39
+ fits, because each check is one durable ordered message, and a limiter that
40
+ every request touches does not.
41
+ - Point the high-QPS reader at [Solid Objects Pro](https://solidobjects.pro/)
42
+ from the rate-limit sentence in the README and `docs/fit.md`, and name what
43
+ it adds for that shape: grouped commits and ephemeral operations. The README
44
+ states that it ships for the Rails gem today and that the Node build is in
45
+ development.
46
+ - Move the early-release caveat off the first screen. It is now a `Status`
47
+ section at the end of the README, with a table-of-contents entry, which
48
+ matches where the Ruby gem keeps the same statement. The first screen keeps
49
+ the transaction caveat, because that one changes whether a reader should
50
+ install anything.
51
+ - State the workflow limit next to the workflow row instead of only in
52
+ `docs/fit.md`. A workflow fits when one entity owns the mutable state and its
53
+ mailbox holds the step order. A durable execution engine that replays named
54
+ steps from a step log is a different tool.
55
+
56
+ ## 0.14.3 - 2026-08-25
57
+
58
+ - Rewrite the first screen around the objection a reader actually has. The
59
+ README led with a shopping cart that appended to an array, which invites the
60
+ reply that one SQL statement already does it. It now leads with the ticket
61
+ sale from the homepage: 100 seats, a hold, a ten-minute expiry that frees the
62
+ seat, and a published count. That is the smallest example needing three
63
+ things from one number, and the three things are the argument.
64
+ - Answer "why not just use transactions?" in the first screen instead of
65
+ burying the fit sections. The section concedes the transaction and the row
66
+ lock first, including `navigator.locks` in the browser, then argues scope
67
+ rather than discipline: any `expiresAt` or `scheduledAt` column is evidence
68
+ the critical section already outlived the lock, and what follows it is a
69
+ sweeper and a race.
70
+ - Add "Is it worth installing here?", which names who should not install this,
71
+ and point readers with high-QPS reads or hot identities at
72
+ [Solid Objects Pro](https://solidobjects.pro/).
73
+ - Correct two claims. The realtime section said a value is published once per
74
+ change from the saving turn; the turn records the publication atomically,
75
+ while delivery is a separate worker and is at least once. Design provenance
76
+ said the API was redesigned around Web Components; there is no
77
+ `customElements` or `HTMLElement` in the package.
78
+ - Cut the README from 590 to about 540 lines by removing what `docs/` already
79
+ documented and what the page said three times, and add the table of contents
80
+ the standard-readme specification asks for above 100 lines.
81
+
3
82
  ## 0.14.2 - 2026-08-24
4
83
 
5
84
  - State that background pickup needs `runtime.run(signal)`
@@ -136,8 +215,8 @@
136
215
  `createdAtMs` rather than comparing `instanceId` values directly.
137
216
  `createdAtMs` orders incarnations at millisecond granularity; destroying
138
217
  and recreating the same actor identity within the same millisecond
139
- produces two incarnations a caller cannot order by `createdAtMs` alone
140
- see `docs/correctness.md`.
218
+ produces two incarnations a caller cannot order by `createdAtMs` alone.
219
+ See `docs/correctness.md`.
141
220
 
142
221
  ## 0.13.3 - 2026-08-18
143
222