Skip to content

Port upstream c0f9647: one temporal encoder for the Python JSON writer - #2

Merged
robfrank merged 1 commit into
mainfrom
port-upstream-c0f9647
Oct 22, 2026
Merged

robfrank merged 1 commit into
mainfrom
port-upstream-c0f9647

Conversation

@robfrank

Copy link
Copy Markdown
Contributor

Ports the bindings/python part of ArcadeData/arcadedb@c0f96479da (ArcadeData/arcadedb#10564, by @lvca). It landed upstream after the move was extracted at ee04bd2, so the bindings here missed it. It is also what makes ArcadeData/arcadedb#10615 conflict.

The commit keeps its original author and changes:

The upstream commit was filtered to bindings/python and applied with git am --3way, with no conflicts. Its message now says ArcadeData/arcadedb#N and names the source commit.

Verified locally: darwin/arm64 wheel built against arcadedata/arcadedb:latest (26.11.1-SNAPSHOT), and the full suite passed: 1059 passed, none skipped.

Once this is merged, ArcadeData/arcadedb#10615 gets rebased onto upstream main and also deletes test_temporal_writers_agree.py.

🤖 Generated with Claude Code

…arcadedb#10426): a held database is UNAVAILABLE on every wire protocol, one temporal encoder for the Python JSON writer, a failed snapshot restore keeps schema.json (ArcadeData/arcadedb#10564)

* fix(ArcadeData/arcadedb#10553, ArcadeData/arcadedb#10522, ArcadeData/arcadedb#10426): a held database is UNAVAILABLE on every wire protocol, the Python JSON writer has no temporal encoder of its own, a failed snapshot restore keeps schema.json in the backup

ArcadeData/arcadedb#10553: ErrorCategory.UNAVAILABLE (DatabaseNotAvailableException without its not-found subtype) decided once in the engine. gRPC UNAVAILABLE, Postgres 57P03, Bolt DatabaseUnavailable, Redis LOADING and MongoDB 365 TemporarilyUnavailable now read it from the category instead of a private predicate each. Redis also took a held database's prefix for part of a plain key and acknowledged the write into the connection's own bucket; ArcadeDBServer.isDatabaseHeld() lets it recognise the name.

ArcadeData/arcadedb#10522: RowBatcher drops its own LocalDate/Calendar encoder and writes through the engine's JSONObject like every other row shape, so a date past the range of a long of milliseconds is ISO text instead of failing the whole batch. The days form of Result.to_json() for a record row is the engine's round-trip form and is documented and pinned, not copied.

ArcadeData/arcadedb#10426: SnapshotInstaller.restoreBackup moved entries back in directory-listing order, which APFS sorts and ext4/overlayfs/tmpfs do not, so schema.json left the backup before a failing move on Linux only. The schema files now go back last.

* test(ArcadeData/arcadedb#10522): a bridge that follows an engine which cannot write a far date raises ArcadeDBError, not a bare Java exception

The Python jobs of CI bundle the engine of the published snapshot image, whose JSONObject still throws on a date past year 292 million; the bridge follows it, and the bindings raise a Java failure of a read as ArcadeDBError. Verified locally with that image's engine jar.

* review(ArcadeData/arcadedb#10553): the manual recovery text names the installer's own entries by exact name, a held Redis default database is refused, Bolt's parsing catches answer through the category

SnapshotInstaller: the refusal no longer says to keep every entry starting with .snapshot (a bucket may legally be named so, ArcadeData/arcadedb#9446); it lists SNAPSHOT_MACHINERY_FILES and SNAPSHOT_MACHINERY_DIRS by name. RedisNetworkExecutor: a held REDIS_DEFAULT_DATABASE is recorded as the connection's database so an unprefixed write is answered LOADING and not kept in the connection-local bucket. BoltNetworkExecutor: both CommandParsingException catches of RUN answer through classifyExecutionError, which keeps a genuine syntax error's title and lets a held database wrapped by that exception say what it is.

* review(ArcadeData/arcadedb#10553): a close command marks the database before it leaves the registry, so a lock-free reader that finds it gone finds it held

removeDatabase deregistered first and marked second, leaving an instant where isDatabaseHeld() and existsDatabase() were both false for a database a close command was closing. The mark now goes up first; callers read existsDatabase() then isDatabaseHeld(), which the Javadoc says.

* review(ArcadeData/arcadedb#10553): the manual recovery steps are a numbered list, the Redis call site says why existsDatabase comes before isDatabaseHeld

* fix(ArcadeData/arcadedb#10426): the installer's entry names for the recovery text are computed, not a static String that the machinery guards read as a file

SnapshotManagerTest and Issue9446SnapshotPrefixedBucketTest treat every static String of SnapshotInstaller whose value starts with .snapshot as one more entry the install writes into a database directory; the constant added for the recovery text matched. It is a method now.

* review(ArcadeData/arcadedb#10426): the refusal of a retained backup sends the operator to the restart-time recovery and deletes nothing by hand

A live entry absent from .snapshot-backup can be an original the failed install never moved into it (failure during BACKING_UP) or an entry already moved back by the failed restore; a name does not tell which, so no step of the message deletes one. The unused helper that listed the installer's entry names is gone.

Ported from ArcadeData/arcadedb@c0f9647 (bindings/python part only),
which landed upstream after the move was extracted at ee04bd2.
@robfrank
robfrank merged commit 81da4b7 into main Oct 22, 2026
46 checks passed
@robfrank
robfrank deleted the port-upstream-c0f9647 branch October 22, 2026 22:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants