Skip to content

Publish datastore metadata safely for concurrent AST construction - #37

Open
lm-sousa wants to merge 5 commits into
dir-fixesfrom
ast-flatbuffers
Open

lm-sousa wants to merge 5 commits into
dir-fixesfrom
ast-flatbuffers

Conversation

@lm-sousa

@lm-sousa lm-sousa commented Oct 3, 2026

Copy link
Copy Markdown
Member

Concurrent eager AST construction can race while shared datastore key metadata is initialized. Publish the key map during construction and use ConcurrentHashMap.computeIfAbsent for shared key indexes. The production branch uses ordinary eager stores; deferred store experiments are preserved on lazy-flatbuffers-experiment.

Includes the temporary/cache folder helpers used by the consumer resource lifecycle. Stacked on #34.

Validated at ff2b543328c585376b64aded0d15778b6c67d59b: 1,737 tests passed and JaCoCo verification passed, including the concurrent initialization regression.

- SpecsIo.createTempDirectory(prefix): unique directory allocated by the
  OS under the user temp folder, registered for deletion on exit as a
  backstop, so callers no longer hand-roll UUID/timestamp names
- SpecsIo.getOsCacheFolder(): user-level cache folder following OS
  conventions (XDG_CACHE_HOME, ~/Library/Caches, %LOCALAPPDATA%)
- SpecsSystem.isMac()
Add a backed store that decodes individual fields on first access, preserves deferred copies, and lets typed writes replace pending values. Verify storage semantics and run the full jOptions suite and coverage gate.
Build definition key maps before publication and use a concurrent cache for slot indexes. Parallel first readers previously observed incomplete maps, causing lazy AST imports to reject valid fields. Add a concurrent first-use test that reproduces the old failure.
Remove the FlatBuffers lazy datastore and slot resolution hooks from the eager production branch. Preserve the concurrency regression using ordinary stores; the complete lazy implementation remains on lazy-flatbuffers-experiment. Validation: jOptions tests and JaCoCo coverage gate pass.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff2b543328

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

this.appName = appName;
this.sections = new ArrayList<>(sections);
this.defaultData = defaultData;
this.keyMap = new HashMap<>(StoreDefinition.super.getKeyMap());

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Build the key map without dispatching to subclasses

StoreDefinition.super.getKeyMap() calls getKeys() virtually. If a downstream AStoreDefinition subclass overrides getKeys() and reads fields initialized after super(...), construction now sees uninitialized state and can throw or permanently cache an incomplete map; previously the lazy lookup occurred only after construction. Populate the map directly from the initialized sections or through a non-overridable base method.

Useful? React with 👍 / 👎.

File tempFolder = Files.createTempDirectory(getTempFolder().toPath(), prefix).toFile();

// Backstop deletion, in case the owner does not get the chance to delete it
deleteOnExit(tempFolder);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Make temp-directory cleanup cover later contents

When callers put files into the returned directory, this registration does not provide the documented shutdown backstop: deleteOnExit traverses the directory immediately while it is still empty, so subsequently created children are never registered and deletion of the now-nonempty directory fails at JVM exit. Use cleanup that traverses at shutdown, or otherwise ensure later contents are removed before deleting the directory.

Useful? React with 👍 / 👎.

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.

1 participant