solid-objects 0.14.3 → 0.14.5

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,68 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.14.5 - 2026-08-29
4
+
5
+ - Record the Ruby state warning in the parity ledger. The row said the Ruby gem
6
+ has no soft threshold. It carries the same `solid_objects.state.large` event
7
+ and the same 5 MB hard default from `0.14.3`, as `warn_state_bytes`. Its
8
+ threshold defaults to 64 KB rather than 128 KB, because the measured Ruby
9
+ curve falls sooner: the gem keeps 55% of its empty-state throughput at 13 KB
10
+ of state, where this package keeps 98% at 16 KB. Documentation only; no
11
+ runtime change.
12
+
13
+ ## 0.14.4 - 2026-08-29
14
+
15
+ - Cut the per-turn state traversals from eight to four. The runtime built the
16
+ whole state image eight times for each committed operation, and nine times
17
+ for a query, where two are necessary. The commit path now passes the image it
18
+ already holds to the observables guard, and the query check reads the
19
+ committed image instead of taking its own. The guard is unchanged: it still
20
+ reads the state after `observables()` returns, because only that read sees a
21
+ mutation.
22
+ - Compute the default state once for each registered actor class. Every `send`
23
+ and every hydration constructed a throwaway actor and serialized its full
24
+ default state. The constructor must not depend on external state, so one
25
+ cached image per validated definition is correct. Each caller receives a
26
+ detached copy.
27
+ - Stop building a string that `normalizeJson` discards. It called
28
+ `JSON.stringify` on every value, then used the result only when a byte limit
29
+ was given. `actorState`, `deepCopy`, and `stableJson` all pass no limit.
30
+ - Measured on an Apple M5 with SQLite: 1.2x throughput at 0 KB of state, 1.3x
31
+ at 16 KB, 1.6x at 128 KB, and 2.1x at 1 MB. See
32
+ [Large state](docs/benchmarks.md#large-state).
33
+ - Add `warnStateBytes`, a soft threshold that defaults to 128 KB. A commit
34
+ above it reports one `solid_objects.state.large` instrumentation event with
35
+ the actor type, the actor ID, the byte count, and the threshold. The runtime
36
+ reports it only after the commit succeeds, so a turn that rolls back stays
37
+ silent. The event holds no application state, and the runtime measures the
38
+ size only when an `instrumentation` callback is configured. `maxStateBytes` keeps its 5 MB hard
39
+ default, which fails the turn. Throughput at that size is about one operation
40
+ per second, so the warning names the constraint before an application meets
41
+ it.
42
+ - Add a `large-state` benchmark scenario, `pnpm run benchmark:large-state`,
43
+ that reports operations per second at 0 KB, 16 KB, 128 KB, and 1 MB, and
44
+ document the measured curve in `docs/state-and-lifecycle.md`.
45
+
46
+ - Align the use-case claims with the Ruby gem. The README table sold per-key
47
+ rate limits, while the Ruby fit guide called a rate limiter an anti-pattern.
48
+ Both projects now draw one line: a low-rate quota that a reminder refills
49
+ fits, because each check is one durable ordered message, and a limiter that
50
+ every request touches does not.
51
+ - Point the high-QPS reader at [Solid Objects Pro](https://solidobjects.pro/)
52
+ from the rate-limit sentence in the README and `docs/fit.md`, and name what
53
+ it adds for that shape: grouped commits and ephemeral operations. The README
54
+ states that it ships for the Rails gem today and that the Node build is in
55
+ development.
56
+ - Move the early-release caveat off the first screen. It is now a `Status`
57
+ section at the end of the README, with a table-of-contents entry, which
58
+ matches where the Ruby gem keeps the same statement. The first screen keeps
59
+ the transaction caveat, because that one changes whether a reader should
60
+ install anything.
61
+ - State the workflow limit next to the workflow row instead of only in
62
+ `docs/fit.md`. A workflow fits when one entity owns the mutable state and its
63
+ mailbox holds the step order. A durable execution engine that replays named
64
+ steps from a step log is a different tool.
65
+
3
66
  ## 0.14.3 - 2026-08-25
4
67
 
5
68
  - Rewrite the first screen around the objection a reader actually has. The
@@ -162,8 +225,8 @@
162
225
  `createdAtMs` rather than comparing `instanceId` values directly.
163
226
  `createdAtMs` orders incarnations at millisecond granularity; destroying
164
227
  and recreating the same actor identity within the same millisecond
165
- produces two incarnations a caller cannot order by `createdAtMs` alone
166
- see `docs/correctness.md`.
228
+ produces two incarnations a caller cannot order by `createdAtMs` alone.
229
+ See `docs/correctness.md`.
167
230
 
168
231
  ## 0.13.3 - 2026-08-18
169
232