magus v0.4.3 is out. See what's new
¶ View markdown source · ✎ Suggest an edit
3 min read

MGS3032: an unordered share of one claimable file

magus job fork, the client tool (magus\job.put) and a magusfile's magus\job.put refused a job because one of its write paths and another live job's write path, held in a different checkout, name the same file, and nothing orders the two jobs against each other:

[MGS3032] job: wave/b declares "magusfile.buzz", and wave/a (running, updated
  4m3s ago) already holds "magusfile.buzz". Both are live and neither is the
  other's parent, child, or depends_on partner, so magusfile.buzz has one
  owner unless the rows say otherwise. wave/a has touched none yet in it so
  far. Claim `magusfile.buzz#<declaration>` on both rows, add `--depends-on
  wave/a` to wave/b, or fold wave/b into wave/a

Nothing was written to the job store.

Why

A whole-file write path claims the whole file, and two whole-file leases on one file both read "mine wins": neither is ever refused, which is what makes the whole-file spelling look free. It is not free once the file is genuinely shared between two agents working at once, and the plan has three ways to say so: a declaration claim, a depends_on edge, or one job instead of two. This refusal is the fork-time cost that makes naming one of those the cheaper choice. It fires only when magus can prove the fact: the two write paths name one literal file (no glob, no directory, no project root), that file has a diff driver so a declaration claim on it could actually be graded, and neither row's parent chain nor depends_on already sequences the pair.

What is refused

  • Two whole-file entries on one file, held live in two different checkouts, with neither job the other's parent, child, or depends_on predecessor.
  • A whole-file entry against a claim on that file: run.go here and run.go#executeStages there still collide, since the whole-file entry covers every declaration.

What is not refused

  • A glob, a directory, or a project root. Only a single literal file is judged here; the overlap report and MGS3018 cover the rest.
  • A file with no diff driver (.txt, .json, .yaml unless you have registered one). Nothing can grade a declaration of it, so the pair is recorded, not refused; depends_on is the only move.
  • Two claims on different declarations of one file (run.go#A and run.go#B): that is exactly what a claim is for.
  • A pair already ordered: a parent and its child, or two jobs joined by depends_on, directly or through any number of hops, in either direction.
  • Two rows held in the same checkout, or a row not yet taken into one (CheckoutRoot empty). That is what RefuseSharedCheckout and write_proof: overlapping already watch; sharing a file there stays an advisory the orchestrator that declared both rows can act on.
  • A holder blocked on depends_on. A blocked row owns none of its write paths yet, so it cannot collide today; the fork that unblocks it runs this same check again, against whatever holds the file then.
  • A holder whose job has exited. Its holder returned, so its editing is over; the row stays until job wait grades it or its work lands on the base, but it holds no file against a new fork.

What to do

Claim a declaration on both rows, so the two jobs partition the file instead of racing on it:

magus job fork wave/a --write-paths magusfile.buzz#lint_rules
magus job fork wave/b --write-paths magusfile.buzz#lint

Or sequence them:

magus job fork wave/b --write-paths magusfile.buzz --depends-on wave/a

Or fold the work into the job that already holds the file.

See also

  • Leases: write paths, claims, and what the guard enforces.
  • MGS3031: a declaration claim nothing can grade.
  • MGS3018: a directory as a job write path.
MGS3032jobsleaseswrite pathsforkagentsclaimsdepends_on
Last updated (479ce5c7)
Earlier changes on this page (4)

Full history ↗ · Blame source ↗

Glossary

Project

A directory magus recognizes as a unit of work (it has a magusfile); the unit of caching, scheduling, and dependency tracking. See workspace.

Magusfile

The magusfile.buzz that declares a project's targets (as export funs) and binds its spells. See targets.

Op

A single tool-native command a target composes (long form: operation); the middle of the work hierarchy (Spell to Op to Target). See operations.

Spell

A language/runtime adapter (e.g. go, md) that maps generic targets onto a toolchain's real commands. See spells.

Buzz

The language magusfiles are written in (the .buzz engine). See engines.

CI

An ordinary magusfile-defined target you compose yourself with magus\needs: magus does not hardcode its stages. Magus.RunCI treats it specially only in that it strips the rw charm, it is the anchor magus affected ci keys off, and a selected scope with no project declaring it is a load error rather than a silent no-op. See targets.

Job

The unit of delegated work, and one row of the job store: what an orchestrating agent handed out, with its goal, the checkpoint it was cut against, the paths it may write or must not touch, and the one check it runs. A job's holder is either a session, for work an orchestrator handed out, or the server, for its own maintenance. The store records; the agent guard is what reads those facts back when grading a write. See doctrine.

A job is not a run. magus run build web is a run, and no job exists for it. A job causes runs: its check executes as one, and a server job records the invocation of its last one. Jobs are listed with magus ls jobs and in the console's Jobs view; runs are listed in the Runs view.

Run

One target executing under one magus invocation, such as magus run test web or magus affected ci. A run keeps its captured output behind an output reference. Every magus run is a run whether or not any job asked for it; see Job for how the two relate.

Lease

The grant a holder takes on a job: the write and read paths that job declared, enforced in the checkout that took it with magus job exec. A job is the piece of work; a lease is permission over it.

Advisor

One read-only check from the advice suite: it reads the changeset through magus and writes one titled section of findings. The same advisors run as a pull request comment in CI and inside magus diff --impact locally.

Conventions

This page uses none of the site's convention markers. The full set is on the conventions page.