Skip to content

fix(ci): use per-call temp dir in DNA templating to fix race-condition flake#857

Merged
lucksus merged 1 commit into
devfrom
fix/ci-template-dna-race-condition
Jun 11, 2026
Merged

fix(ci): use per-call temp dir in DNA templating to fix race-condition flake#857
lucksus merged 1 commit into
devfrom
fix/ci-template-dna-race-condition

Conversation

@HexaField

@HexaField HexaField commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Summary

read_and_template_holochain_dna (in rust-executor/src/languages/mod.rs) used temp_dir().join(source_language_hash) as its working directory, so every templating call against the same source language landed on the same /tmp/<hash>/ path. The top of the function wipes that path via fs::remove_dir_all before recreating it — which means concurrent calls against the same source language race each other.

Two integration tests in tests/js/tests/neighbourhood.ts both call languages.applyTemplateAndPublish(DIFF_SYNC_OFFICIAL, ...) against the shared perspective-diff-sync hash:

  • can be created by Alice and joined by Bob
  • shared link created by Alice received by Bob

On busy CircleCI workers the second call regularly enters the function while the first is still mid-pipeline (between unpack_happ and pack_happ). The second call's fs::remove_dir_all wipes the first's working directory, and the first's eventual pack_happ blows up with:

Failed to pack hApp: ffs::IoError at path
'/tmp/QmzSY…/happ/happ.yaml': No such file or directory (os error 2)

This has been the long-standing flake on integration-tests-js. It surfaced again under the #837 / #842 stack and has been recurring across CI runs.

Fix

Switch to a per-call UUID-suffixed temp dir:

let temp_templating_path = std::env::temp_dir().join(format!(
    "{}-{}",
    source_language_hash,
    uuid::Uuid::new_v4()
));
  • Concurrent templates can no longer race on the same path.
  • The existing end-of-function fs::remove_dir_all(&temp_templating_path) still removes the per-call dir on the happy path.
  • An earlier-failing call only leaves a uniquely-named orphan rather than poisoning the next call.
  • uuid is already a workspace dependency (uuid = "1.3.0").

Test plan

  • cargo check -p ad4m-executor --lib clean
  • cargo fmt --check clean
  • Full CircleCI integration-tests-js green on this branch

Summary by CodeRabbit

  • Bug Fixes
    • Fixed intermittent failures in DNA/HApp templating operations that occurred when multiple concurrent invocations were processed simultaneously. The system now properly isolates concurrent operations to prevent them from interfering with each other's intermediate artifacts.

…n flake

The Holochain DNA templating helper inside `read_and_template_holochain_dna`
used `temp_dir().join(source_language_hash)` as its working directory. That
meant every templating call against the same source language landed on the
same `/tmp/<hash>/` path, with the top of the function wiping that path via
`fs::remove_dir_all` before recreating it.

Two integration tests in `tests/js/tests/neighbourhood.ts` both call
`languages.applyTemplateAndPublish(DIFF_SYNC_OFFICIAL, ...)` against the
shared `perspective-diff-sync` hash —

  - "can be created by Alice and joined by Bob"
  - "shared link created by Alice received by Bob"

— and on the busy CircleCI workers the second call regularly entered the
function while the first was still mid-pipeline (between `unpack_happ`
and `pack_happ`). The second call's `fs::remove_dir_all` wiped the
first's working directory, and the first's eventual `pack_happ` blew up
with:

    Failed to pack hApp: ffs::IoError at path
    '/tmp/QmzSY…/happ/happ.yaml': No such file or directory (os error 2)

That's been the long-standing flake on `integration-tests-js`.

Switch to a per-call UUID-suffixed temp dir
(`<temp_dir>/<source_hash>-<uuid_v4>/`). Concurrent templates can no
longer race on the same path, the existing end-of-function cleanup still
removes the per-call dir, and an earlier-failing call only leaves a
uniquely-named orphan rather than poisoning the next call. `uuid` is
already a workspace dependency (`uuid = "1.3.0"`).
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1aa33d17-156a-4ce9-b44b-646d3a405112

📥 Commits

Reviewing files that changed from the base of the PR and between f3882a5 and f667453.

📒 Files selected for processing (1)
  • rust-executor/src/languages/mod.rs

📝 Walkthrough

Walkthrough

The read_and_template_holochain_dna function now appends a UUID to the source language hash when creating its temporary working directory, replacing the shared hash-only path. This prevents concurrent invocations from racing on the same directory and deleting each other's intermediate artifacts during template and publish operations.

Changes

DNA Templating Concurrency Fix

Layer / File(s) Summary
Per-invocation unique temp directory
rust-executor/src/languages/mod.rs
The temporary working directory for DNA/HApp templating operations now includes a UUID suffix appended to the source language hash, isolating each invocation's unpack/pack artifacts and preventing race conditions where concurrent calls would overwrite or delete each other's files mid-pipeline.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 A race once plagued the temp-dir lane,
Where files collided, chaos reigned.
Then UUID came, a bunny's delight,
Each call gets its own unique site!
No more stepping on paws today,
Concurrency fixed in the rabbit's way! 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and specifically summarizes the main change: fixing a race condition in DNA templating by using per-call temporary directories instead of shared hash-only paths.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ci-template-dna-race-condition

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lucksus lucksus merged commit f852873 into dev Jun 11, 2026
8 checks passed
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