Repository navigation
Lifecycle: results and records keep their Database and raise once it is closed; failed create_vertices rolls back; set reads back as a list (#117, #121, #122) - #130
Merged
Conversation
create_vertices opens its transaction inside the engine and the engine rolls it back only for a retryable error. A duplicate key (or a KeyboardInterrupt) left it active, so a later write outside any transaction was accepted and lost at close. Roll back, as create_vertex does, when the call started the transaction, and leave one the caller already had open alone. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeKEhHXJTy1H1GgbfBZ8mL
…s closed
ResultSet, Result, and the record wrappers took only the Java object, so
Database.close() (or Database.__del__ when the wrapper was collected) left them
reading through a closed database: a record row came back as {}, a record
property as None, and a plain scan raised a raw TransactionException, with the
engine logging "Possible corrupted record" for each read.
The wrappers now hold the Database that produced them. That keeps the database
open while any of them is alive, which is what stops Database.__del__ from
closing it under a returned result, and every read checks the flag and raises
ArcadeDBError("Database is closed"), as db.query does. A result set read to its
end still reads as empty. The engine half (BinarySerializer swallowing
DatabaseIsClosedException) is reported upstream separately.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DeKEhHXJTy1H1GgbfBZ8mL
…ter the commit The conversion page said a set becomes a HashSet and reads back as a set. That holds only for the record of the transaction that set it: the engine has no set type, so the HashSet is serialized as a list at commit and every later read returns a list. Correct the tables and examples, add a note to the collection section, and pin the behavior with a test that fails if the engine ever keeps sets. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeKEhHXJTy1H1GgbfBZ8mL
This was referenced Oct 3, 2026
…tabase is closed The examples job caught it: example 16 reads the Result of IMPORT DATABASE after closing the database it ran on, and the rule that refused every Result after close made it fail on macOS and on Linux with Python 3.14. Only a row that is a record (SELECT FROM T) loads its properties lazily from the open database; a projection or a command result holds its own values. Result._check_open now raises only for a record row. A result SET that was not read to its end still raises, since its remaining rows may be read lazily from the engine. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DeKEhHXJTy1H1GgbfBZ8mL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #121, #122, and #117. The engine halves are filed upstream: ArcadeData#9038 (
BinarySerializerswallowingDatabaseIsClosedException, for #117) and ArcadeData#9040 (GraphBatch.createVerticesrolling back only for aNeedRetryException, for #121).#121.
GraphBatch.create_verticesopens its transaction inside the engine and the engine rolls it back only for a retryable error, so a duplicate key (or aKeyboardInterrupt) left it active and a later write outside any transaction was accepted and lost at close. The wrapper now rolls back, ascreate_vertexdoes after ArcadeData#8828, when the call started the transaction, and leaves one the caller already had open alone. Three tests: JSON-bulk and property-matrix paths, the caller's own transaction, and aKeyboardInterruptafter the engine's transaction began.#117.
ResultSet,Result, and the record wrappers now hold theDatabasethat produced them and check it on every read, so a read afterclose()raisesArcadeDBError("Database is closed")asdb.querydoes, instead of returning{}orNoneor a rawTransactionException. Holding the reference also keeps the database open while a result is alive, which is what stopsDatabase.__del__from closing it under a returned result. A result set read to its end still reads as empty. The consequence is documented and tested: while a result is alive the engine refuses a secondopen_database()of the same path ("already in use"), and with every result and record gone the wrapper's__del__closes the database and the path opens again. Only a row that is a record (SELECT FROM T) needs the open database, so a projection or commandResultthat was already returned keeps its own values and stays readable afterclose(), and an unread result set raises. My first version refused everyResult; the examples job caught that: example 16 reads theIMPORT DATABASEresult after closing its database (macOS, and Linux with Python 3.14), which is fixed in the last commit and covered by a test.#122. The conversion page said a
setreads back as aset. That holds only inside the transaction that set it: the engine has no set type, so theHashSetis serialized as a list at commit. The tables, examples, and collection section are corrected, and a test pins the behavior so it fails if the engine ever keeps sets.Verified: the new tests fail on
origin/main(4 of 6 new tests for #117, 3 of 4 for #121; the rest are guards against regressing the other way) and pass with the change, the full suite passes (521 passed, 3 skipped, 3 xfailed), example 16 passes at its CI arguments, and bandit is clean at CI strictness.🤖 Generated with Claude Code
https://claude.ai/code/session_01DeKEhHXJTy1H1GgbfBZ8mL