feat(store): add tines-store persistent append-only LogStore

Add the host-side std `tines-store` crate implementing the `tines_core::Store`
trait over a durable, append-only single-file log so a robot's memory survives
reboot.

- Log format: length-prefixed `[u32 LE][postcard]` records (Obs/Trim/Meta).
- On load the index is rebuilt by replaying the log, then every age is
  rebased to load time: elapsed time since the last persisted clock marker is
  folded into `age_ms` and `stored_at` reset to load `now`, so ages continue
  instead of freezing across a reboot.
- Persisted state: released-id set, `next_seq`, and a clock marker in a `Meta`
  record; dedupe to the oldest Obs and let the last event per id win so a
  re-inserted id survives a trim.
- Implements `next_seq` and `flush`; `trim` writes Trim records best-effort.
- Registered as a workspace member; std-only, `#![forbid(unsafe_code)]`.
- Adds persistence tests (append durability, rebase-on-load, released/seq
  persistence). Full gate (fmt, clippy, docs, tests, no_std thumb build) is green.
This commit is contained in:
2026-10-18 12:43:42 -07:00
parent f9613b1c32
commit 43b73f88cd
6 changed files with 609 additions and 3 deletions
Generated
+103 -2
View File
@@ -2,6 +2,15 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "atomic-polyfill"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4"
dependencies = [
"critical-section",
]
[[package]]
name = "autocfg"
version = "1.5.1"
@@ -134,6 +143,12 @@ dependencies = [
"libc",
]
[[package]]
name = "critical-section"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
[[package]]
name = "crypto-common"
version = "0.1.7"
@@ -155,6 +170,18 @@ dependencies = [
"subtle",
]
[[package]]
name = "embedded-io"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ef1a6892d9eef45c8fa6b9e0086428a2cca8491aca8f787c534a3d6d0bcb3ced"
[[package]]
name = "embedded-io"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"
[[package]]
name = "equivalent"
version = "1.0.3"
@@ -216,6 +243,15 @@ dependencies = [
"rand_core 0.10.1",
]
[[package]]
name = "hash32"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67"
dependencies = [
"byteorder",
]
[[package]]
name = "hash32"
version = "0.3.1"
@@ -231,13 +267,27 @@ version = "0.17.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a"
[[package]]
name = "heapless"
version = "0.7.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f"
dependencies = [
"atomic-polyfill",
"hash32 0.2.1",
"rustc_version",
"serde",
"spin",
"stable_deref_trait",
]
[[package]]
name = "heapless"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
dependencies = [
"hash32",
"hash32 0.3.1",
"serde",
"stable_deref_trait",
]
@@ -264,6 +314,15 @@ version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
[[package]]
name = "lock_api"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
dependencies = [
"scopeguard",
]
[[package]]
name = "memchr"
version = "2.8.3"
@@ -292,6 +351,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6764c3b5dd454e283a30e6dfe78e9b31096d9e32036b5d1eaac7a6119ccb9a24"
dependencies = [
"cobs",
"embedded-io 0.4.0",
"embedded-io 0.6.1",
"heapless 0.7.17",
"serde",
]
@@ -424,6 +486,15 @@ version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4"
[[package]]
name = "rustc_version"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
dependencies = [
"semver",
]
[[package]]
name = "rustix"
version = "1.1.5"
@@ -449,6 +520,18 @@ dependencies = [
"wait-timeout",
]
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "semver"
version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
[[package]]
name = "serde"
version = "1.0.229"
@@ -479,6 +562,15 @@ dependencies = [
"syn 3.0.9",
]
[[package]]
name = "spin"
version = "0.9.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
dependencies = [
"lock_api",
]
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -551,7 +643,7 @@ name = "tines-core"
version = "0.3.0"
dependencies = [
"blake2",
"heapless",
"heapless 0.8.0",
"postcard",
"serde",
]
@@ -565,6 +657,15 @@ dependencies = [
"tines-core",
]
[[package]]
name = "tines-store"
version = "0.3.0"
dependencies = [
"postcard",
"serde",
"tines-core",
]
[[package]]
name = "toml_datetime"
version = "1.1.2+spec-1.1.0"