Šķîþ ţö ḿàîñ çöñţéñţ

Ŵöŕķšþàçé šţöŕàĝé

Ţĥé ƒîļéš à ŵöŕķšþàçé ķééþš, ţĥé ţàƃļéš îñ éàçĥ þööļ, àñđ ĥöŵ ķàþî öþéñš àñđ ǫüéŕîéš ţĥéḿ. Þàŕéñţ ÀĐ: Ç-03.

Ţĥé ƒîļéš​

À ŵöŕķšþàçé îš à đîŕéçţöŕý öƒ ŠǪĻîţé đàţàƃàšéš, çŕéàţéđ öñ ƒîŕšţ üšé (core/workspace.LocalBackend):

<DataDir>/workspaces/default/
workspace.db the project registry, the context graph,
the operation log, widened rules, agent sessions
projects/
prj_9f2k…q7.db one project's context store
prj_4c8m…b1.db

workspace.RegistryFileName îš workspace.db àñđ workspace.ProjectsDirName îš projects. À þŕöĵéçţ'š ƒîļé îš FileNameFor(key) + ".db": ţĥé ķéý ṽéŕƃàţîḿ ŵĥéñ îţ îš àļŕéàđý à šàƒé ƒîļé ñàḿé (1 ţö 64 çĥàŕàçţéŕš öƒ a-z, 0-9, - àñđ _), šö à đîŕéçţöŕý ļîšţîñĝ ŕéàđš àš ţĥé þŕöĵéçţš îţ ĥöļđš, àñđ öţĥéŕŵîšé à šàñîţîžéđ þŕéƒîẋ öƒ àţ ḿöšţ 32 ƃýţéš ƒöļļöŵéđ ƃý ţĥé ƒîŕšţ éîĝĥţ ƃýţéš öƒ ţĥé ķéý'š ŠĤÀ-256 îñ ĥéẋ. Àñ éḿþţý ķéý ƒîļéš üñđéŕ unidentified.db.

À ŕéçîþé ţĥàţ šţàţéš ñéîţĥéŕ àñ id: ñöŕ à name: ţàķéš workspace.KeyForCheckout(normalizedRoot): at_ ƒöļļöŵéđ ƃý ţĥé ƒîŕšţ ţéñ ƃýţéš öƒ SHA-256 öṽéŕ ţĥé šļàšĥ-šéþàŕàţéđ ñöŕḿàļîžéđ çĥéçķöüţ þàţĥ, îñ ļöŵéŕçàšé üñþàđđéđ ƃàšé32.

Ţĥé þŕöĵéçţîöñ šţàýš îñ ţĥé çĥéçķöüţ àţ .kapi/work/store.db (project.Layout.StorePath()).

Ţĥé ţàƃļéš éàçĥ þööļ ĥöļđš​

Ţàƃļ隊üƃšýšţéḿÞööļ
ƃļöçķ çàçĥé, öṽéŕļàýšcore/blockstoreþŕöĵéçţîöñ
store_metacore/projectdbþŕöĵéçţîöñ
tb_*terms/çöñţéẋţ
tm_*memory/çöñţéẋţ
voice_*voice/çöñţéẋţ
unit_decision, unit_view, document, document_adoption, checkout, state_metacore/stateçöñţéẋţ
block_history, block_history_opcore/historyçöñţéẋţ
edition_head, edition_subject_head, document_headcore/workhomeçöñţéẋţ
projector_cursorcore/projectorçöñţéẋţ
graph_nodes, graph_edgeshost/storage/graphŵöŕķšþàçé
workspace_projects, workspace_checkoutscore/workspaceŵöŕķšþàçé
workspace_ops (àŕŕîṽàļ seq, öþéŕàţîöñ id, öþţîöñàļ çöñţéñţ address, öþţîöñàļ subject)core/workspaceŵöŕķšþàçé
workspace_blobs (sha256: đîĝéšţ, šîžé, ĝžîþ-çöḿþŕéššéđ ƃýţéš)core/workspaceŵöŕķšþàçé
workspace_rulescore/workspaceŵöŕķšþàçé
workspace_agent_sessionscore/workspaceŵöŕķšþàçé

Éàçĥ šüƃšýšţéḿ ḿîĝŕàţéš îţš öŵñ šçĥéḿà üñđéŕ îţš öŵñ ļéđĝéŕ ţàƃļé (storage.Migrate(db, "<subsystem>", …)), šö à šüƃšýšţéḿ éṽöļṽéš ŵîţĥöüţ ŕéþļàýîñĝ àñýöñé éļšé'š ḿîĝŕàţîöñš, ŵĥîçĥéṽéŕ þööļ îţ ƃîñđš ţö. Ţĥé ŕüļéš àñđ šéššîöñš šçĥéḿàš ḿîĝŕàţé ļàžîļý öñ ƒîŕšţ üšé, šö à ŵöŕķšþàçé ŵĥöšé þŕöĵéçţš ŵîđéñéđ ñöţĥîñĝ þàýš ñöţĥîñĝ ƒöŕ ţĥé ţàƃļé.

core/projectdb öþéñš ƃöţĥ þŕöĵéçţ þööļš àñđ ĥàñđš éàçĥ šüƃšýšţéḿ îţš ĥàñđļé. Çàļļéŕš ñàḿé à çàþàƃîļîţý ŕàţĥéŕ ţĥàñ à ƒîļé: Blocks() àñđ BlocksAutocommit() çöḿé ƒŕöḿ ţĥé þŕöĵéçţîöñ, àñđ Memory(), Terms(), Voice(), Work(), History(), Heads() àñđ Raw() ƒŕöḿ ţĥé çöñţéẋţ šţöŕé.

Ţĥé þŕöĵéçţöŕ​

core/projector îš ţĥé öñļý ŵŕîţéŕ öƒ tb_*, tm_*, voice_profiles, voice_profile_versions, unit_decision, document_adoption, block_history, block_history_op, edition_head, edition_subject_head, document_head àñđ workspace_rules (Ç-03). À ŵŕîţé îš ţŵö ţŕàñšàçţîöñš üñđéŕ öñé îñ-þŕöçéšš ḿüţéẋ þéŕ çöñţéẋţ šţöŕé: ţĥé öþéŕàţîöñ îñţö workspace_ops (àñđ îţš šţéþš îñţö workspace_blobs ŵĥéñ ţĥéý þàšš 32 ĶîƂ), ţĥéñ ţĥé šţöŕé çàļļš, ţĥéñ ţĥé çüŕšöŕ. Ţĥé ḿüţéẋ îš ķéýéđ ƃý ţĥé çöñţéẋţ þööļ, šö ţŵö þŕöĵéçţöŕš öṽéŕ öñé šţöŕé îñ öñé þŕöçéšš ţàķé ţüŕñš; à šéçöñđ þŕöçéšš öñ ţĥé šàḿé šţöŕé àþþļîéš ŵĥàţ ţĥé ƒîŕšţ ŕéçöŕđéđ öñ îţš ñéẋţ ŵŕîţé, ƒŕöḿ ţĥé çüŕšöŕ.

À šţéþ šţöŕéš çöñţéñţ-ḿéḿöŕý éñţŕîéš îñ ţĥé .memory.json ƃüñđļé'š éñţŕý ƒöŕḿ (memory/kmb), çöñçéþţš àñđ ŕéļàţîöñš àš ţĥé ţéŕḿš šţöŕé'š öŵñ ĴŠÖÑ, àñđ ṽöîçé þŕöƒîļéš àš core/profile.VoiceProfile. À šţéþ îš àþþļîéđ ŵîţĥ ţĥé šţöŕé çàļļ ţĥàţ ḿàđé îţ, šö Bulk šţéþš ĝö ţĥŕöüĝĥ BulkAddWithStream àñđ šîñĝļé ŵŕîţéš ţĥŕöüĝĥ AddWithStream. À ŕüñ öƒ 32 öŕ ḿöŕé šîñĝļé ŵŕîţéš, îñ öñé ƃàţçĥ öŕ îñ çöñšéçüţîṽé öþéŕàţîöñš đüŕîñĝ à ŕéƃüîļđ, ĝöéš ţĥŕöüĝĥ ReplayWithStream: ţĥé šàḿé ŕöŵš àš AddWithStream, öñé ţŕàñšàçţîöñ, àñđ ţĥé ţŵö ƑŢŠ5 ţàƃļéš ŕéƃüîļţ öñçé àƒţéŕŵàŕđš.

À ļéđĝéŕ éñţŕý îš öñé decision.record öþéŕàţîöñ, àđđŕéššéđ decision:<project>:<entry id>; ŕüñš öƒ ţĥéḿ, ŵĥîçĥ àñ îḿþöŕţ þŕöđüçéš ƃý ţĥé ţĥöüšàñđ, àŕé àþþļîéđ îñ öñé ţŕàñšàçţîöñ ƃý state.ApplyEntries, ļîṽé àñđ îñ à ŕéƃüîļđ.

À đöçüḿéñţ àđöþţîöñ îš öñé document.adopt öþéŕàţîöñ ŵĥöšé šţéþ çàŕŕîéš à state.Adoption (ķéý, þàţĥ, đîĝéšţ, ţĥé çöñţéñţ ĥàšĥ öƒ éàçĥ ƃļöçķ, àñđ prev, ţĥé îđ öƒ ţĥé àđöþţîöñ ţĥé ķéý ĥéļđ), àđđŕéššéđ adopt:<project>: ƒöļļöŵéđ ƃý îţš îđ, state.AdoptionID: ţĥé ĥéẋ ŠĤÀ-256 öṽéŕ ţĥé ķéý, ţĥé þàţĥ, ţĥé đîĝéšţ àñđ prev ĵöîñéđ ƃý ÑÜĻ. Ţĥé đîĝéšţ îš sha256: ƒöļļöŵéđ ƃý ţĥé ŠĤÀ-256 öṽéŕ ţĥé çöñţéñţ ĥàšĥéš ĵöîñéđ ƃý ñéŵļîñéš. state.ApplyAdoptions ķééþš öñé document_adoption ŕöŵ þéŕ ķéý: ţĥé îđ, þàţĥ, đîĝéšţ àñđ çöñţéñţ öƒ ţĥé àđöþţîöñ ŵîţĥ ţĥé ļàţéšţ ḿöḿéñţ (ţîéš ƃŕöķéñ ƃý ţĥé ĝŕéàţéŕ đîĝéšţ, ţĥéñ ţĥé ĝŕéàţéŕ þàţĥ, ţĥéñ ţĥé ĝŕéàţéŕ îđ) àñđ ţĥé éàŕļîéšţ ḿöḿéñţ àš first_at, šö ţĥé ŕöŵš àŕé ţĥé šàḿé ŵĥàţéṽéŕ öŕđéŕ ţĥé öþéŕàţîöñš àŕé àþþļîéđ îñ. Ţĥé ñéẋţ àđöþţîöñ öƒ ţĥé ķéý ñàḿéš ţĥé ŕöŵ'š îđ àš îţš prev, ŵĥîçĥ îš ŵĥàţ ḿàķéš à ŕéţüŕñ ţö àñ éàŕļîéŕ þàţĥ öŕ çöñţéñţ àñ àđöþţîöñ öƒ îţš öŵñ.

Àñ àþþļîéđ éđîţ îš öñé content.edit öþéŕàţîöñ þéŕ đöçüḿéñţ. Îţš þàýļöàđ îš ţĥé projector.Edit îţšéļƒ ŕàţĥéŕ ţĥàñ à ļîšţ öƒ šţéþš:

{
"doc": {"key": "d-7f3c0a91e4b2d6f8", "path": "docs/guide.md"},
"home": "file",
"actor": {"kind": "agent", "name": "claude", "session": "s_01"},
"origin": {"by": "apply"},
"fingerprint": "gov_4b2",
"note": "Point the guide link at the handbook",
"doc_before": "sha256:5e1c…", "doc_after": "sha256:a07d…",
"transitions": [
{"block": "install/p", "key": "u-3f9a1c0e7b2d4a55", "edition": "fr",
"before": "r:3f9a1c0e7b2d4a55", "after": "r:c41e92d07a8b1f30", "basis": "r:9d0e…",
"content_hash": "…", "context_hash": "…", "ops": ["replace_text"],
"runs_before": "blob:sha256:…", "runs_after": "blob:sha256:…"}
],
"overridden": [{"rule": "terms.vocabulary", "message": "…", "fails": true}],
"change_set": "blob:sha256:…",
"blobs": ["sha256:…", "sha256:…", "sha256:…"]
}

runs_before àñđ runs_after ñàḿé ƃļöƃš ĥöļđîñĝ model.CanonicalRunsJSON öƒ ţĥé éđîţîöñ, ţĥé ƃýţéš model.RunsRevision îš çöḿþüţéđ öṽéŕ; à ţööļ'š éđîţ ļéàṽéš ţĥéḿ àñđ change_set öüţ, àñđ çàŕŕîéš öñ éàçĥ đéŕîṽéđ éđîţîöñ'š ţŕàñšîţîöñ à producer, ţĥé model.Origin ţĥé þŕöđüçîñĝ ţööļ šţàḿþéđ (þŕöṽîđéŕ, ḿöđéļ, þŕöƒîļé àñđ ĝöṽéŕñîñĝ çöñţéẋţ ƒîñĝéŕþŕîñţ), ŵĥîçĥ à ƒîļé öƒ šţŕîñĝš ķééþš ñöŵĥéŕé éļšé, àñđ öñ éṽéŕý ţŕàñšîţîöñ ţĥé tool ţĥàţ çĥàñĝéđ ţĥé éđîţîöñ ŵĥéŕé ţĥé ŕéçöŕđ ñàḿéš öñé. ops ļîšţš ţĥé ķîñđš öƒ ţĥé öþéŕàţîöñš ţĥàţ çĥàñĝéđ ţĥé éđîţîöñ, îñ ţĥé öŕđéŕ ţĥéý àþþļîéđ. Àñ öƃšéŕṽéđ éđîţ (àçţöŕ {"kind": "external"}, öŕîĝîñ observed) ķééþš ŕéṽîšîöñš àñđ ĥàšĥéš öñļý àñđ ñàḿéš ñö öþéŕàţîöñ. À ţööļ'š éđîţ ķééþš ñö ŕüñš, éẋçéþţ ţĥàţ à ŵŕîţé ţö ţĥé ŵöŕķšþàçé ĥöḿé ķééþš runs_after ŵĥöéṽéŕ ḿàđé îţ (ƃéļöŵ). Üñđéŕ à đéçļàŕéđ ŕéđàçţîöñ þöļîçý, host.App.EditRecorder ŕéđàçţš ţĥé ŕüñš àñđ ţĥé ñöţé ŵîţĥ ţĥé þŕöĵéçţ'š ŕüļéš ƃéƒöŕé ţĥéý àŕé šţöŕéđ, éàçĥ ŕüñ šéǫüéñçé àš ţĥé šöüŕçé öƒ à ƃļöçķ ñàḿéđ edit:<doc>#<block>@<edition>:<revision> šö ţĥé þŕöĵéçţ ṽàüļţ ķééþš îţš öŕîĝîñàļš üñđéŕ ţĥé çöñţéñţ ţĥéý çàḿé ƒŕöḿ, àñđ ļéàṽéš change_set öüţ; à þöļîçý ŵîţĥ ţĥé entities đéţéçţöŕ ķééþš ñö ŕüñš àñđ ñö ñöţé. blobs ļîšţš éṽéŕý ƃļöƃ ţĥé þàýļöàđ ñàḿéš, ƃéçàüšé workspace.BlobRefs ŕéàđš à þàýļöàđ'š ţöþ-ļéṽéļ blob àñđ blobs àñđ ñöţĥîñĝ đééþéŕ, àñđ ţĥöšé àŕé ţĥé ƃļöƃš à þüšĥ ŵŕîţéš àñđ à þüļļ ƒéţçĥéš. Àñ éđîţ ŵĥöšé ĴŠÖÑ þàššéš 32 ĶîƂ ḿöṽéš îñţö à ƃļöƃ, àñđ ţĥé þàýļöàđ ƃéçöḿéš {"blob": …, "blobs": […]} ŵîţĥ ţĥé šàḿé ļîšţ. Ţĥé öþéŕàţîöñ'š àđđŕéšš îš edit:<project>: ƒöļļöŵéđ ƃý ţĥé ĥéẋ ŠĤÀ-256 öṽéŕ ţĥé þŕöĵéçţ, ţĥé đöçüḿéñţ ķéý, ţĥé àçţöŕ àñđ, ƒöŕ éàçĥ ţŕàñšîţîöñ, îţš ƃļöçķ, ķéý, éđîţîöñ, ŕéṽîšîöñš, ƃàšîš àñđ ţĥé àđđŕéšš öƒ ţĥé öþéŕàţîöñ ţĥàţ ļàšţ ļéƒţ ţĥé éđîţîöñ àţ ţĥé before ŕéṽîšîöñ (history.Store.Reached). Projector.RecordEdits ļööķš ţĥöšé àđđŕéššéš üþ àƒţéŕ çàţçĥîñĝ üþ, üñđéŕ ţĥé þŕöĵéçţöŕ'š ļöçķ, öñé (block, edition, before) àţ à ţîḿé ţĥŕöüĝĥ ţĥé block_history_reached îñđéẋ, àñđ ŕéçöŕđš éṽéŕý éđîţ îţ îš ĝîṽéñ îñ öñé ŵŕîţé ţö ţĥé ļöĝ àñđ öñé çàţçĥ-üþ; RecordEdit îš ţĥé šàḿé çàļļ ƒöŕ öñé éđîţ. Ŵîţĥîñ öñé çàļļ, àñ éđîţ ţĥàţ éẋţéñđš àñ éàŕļîéŕ öñé îñ ţĥé çàļļ ñàḿéš ţĥàţ éđîţ'š àđđŕéšš îñšţéàđ.

Ţĥé þŕöĵéçţöŕ ŵŕîţéš öñé block_history ŕöŵ þéŕ ţŕàñšîţîöñ, ŵîţĥ ţĥé öþéŕàţîöñ îđ àñđ ţĥé öþéŕàţîöñ'š öŵñ îñšţàñţ, šö à ŕéƃüîļđ ŵŕîţéš ţĥé šàḿé ŕöŵš:

ÇöļüḿñĤöļđš
doc, block, edition, opţĥé þŕîḿàŕý ķéý, îñ ţĥé öŕđéŕ ţĥé þéŕ-éđîţîöñ ŕéàđš ŵàļķ îţ: ţĥé đöçüḿéñţ ķéý, ţĥé ƃļöçķ àš ŕéàđ, ţĥé éđîţîöñ ķéý, ţĥé öþéŕàţîöñ
keyţĥé đüŕàƃļé ķéý ŕéçöñçîļîàţîöñ àššîĝñéđ, ŵĥéŕé ţĥéŕé îš öñé
before, after, basiséđîţîöñ ŕéṽîšîöñš, absent ƒöŕ àñ éđîţîöñ çŕéàţéđ öŕ ŕéḿöṽéđ
content_hash, context_hashţĥé ƃļöçķ'š îđéñţîţý šîĝñàļš àƒţéŕ ţĥé çĥàñĝé
actor, actor_name, sessionperson, agent, tool, öŕ external ƒöŕ à çĥàñĝé ḿàđé öüţšîđé ķàþî ţĥàţ à ŕéàđ öƃšéŕṽéđ
originapply, ksed, mcp, browser, desktop, extract, context, flow:<name>, merge, pull öŕ observed
producerţĥé þŕöđüçîñĝ ţööļ'š model.Origin àš ĴŠÖÑ, éḿþţý ŵĥéñ ţĥé ţŕàñšîţîöñ çàŕŕîéš ñöñé
opsţĥé ķîñđš öƒ ţĥé öþéŕàţîöñš ţĥàţ çĥàñĝéđ ţĥé éđîţîöñ, çöḿḿà-šéþàŕàţéđ, éḿþţý ŵĥéñ ñöñé éẋþļàîñš îţ
toolţĥé ţööļ îñ à ƒļöŵ ţĥàţ çĥàñĝéđ ţĥé éđîţîöñ, ŵĥéŕé ţĥé ŕéçöŕđ ñàḿéš öñé
atţĥé öþéŕàţîöñ'š îñšţàñţ, ŔƑÇ 3339 ŵîţĥ ñàñöšéçöñđš îñ ÜŢÇ

À ŵŕîţé ţö ţĥé ŵöŕķšþàçé ĥöḿé îš à content.edit ŵîţĥ "home": "workspace" àñđ üþ ţö ƒöüŕ ḿöŕé ƒîéļđš: edition (ţĥé éđîţîöñ ţĥé ŵŕîţé çĥàñĝéđ, îñ îţš ţéẋţ ƒöŕḿ), base (ţĥé öþéŕàţîöñ ţĥé éđîţîöñ'š ĥéàđ ŵàš àţ ŵĥéñ ţĥé ŵŕîţé ŵàš šţàĝéđ, éḿþţý ƒöŕ ţĥé ƒîŕšţ), cause (ţĥé đîṽéŕĝéñţ öþéŕàţîöñ à ŕéƃàšé çàŕŕîéš öṽéŕ) àñđ release (ţŕüé ƒöŕ à đéļîṽéŕý'š ŕéļéàšé öƒ ţĥé ŵĥöļé éđîţîöñ). Éàçĥ öƒ îţš ţŕàñšîţîöñš àļšö çàŕŕîéš ţĥé éđîţîöñ'š status, îţš origin àñđ, ƒöŕ à þŕöđüçéŕ'š đŕàƒţ, à stamp ({"key", "provider", "config", "source", "runs"}: ţĥé ƃļöçķ-šţöŕé öṽéŕļàý ķéý, ţĥé ŕéüšé ƒîéļđš öƒ ţĥé öṽéŕļàý ţĥé þŕöđüçéŕ šéŕṽéš ţĥé đŕàƒţ ƒŕöḿ, àñđ ţĥé öṽéŕļàý'š ŕüñš ŵĥéŕé à ļàţéŕ šţéþ öƒ ţĥé ƒļöŵ çĥàñĝéđ ţĥé đŕàƒţ). Îţš ţŕàñšîţîöñš çàŕŕý ops àñđ tool àš àñý éđîţ'š đö: à çĥàñĝé šéţ'š ķîñđš, à þŕöđüçéŕ'š đŕàƒţ àš set_content öŕ replace_text (change.EditionKind, ţĥé ķîñđ change.Diff ŵöüļđ šéñđ) ŵîţĥ ţĥé ţööļ ţĥé ƒļöŵ ñàḿéš, àñđ à ŕéļéàšé àš remove_edition. À ŕéƃàšé çàŕŕîéš ţĥé ţŕàñšîţîöñš öƒ ţĥé ŵŕîţé îţ çàŕŕîéš öṽéŕ, ŵîţĥ ţĥéîŕ ķîñđš àñđ ţööļ. Üñđéŕ à đéçļàŕéđ ŕéđàçţîöñ þöļîçý ţĥé ŕüñš àñđ ţĥé ñöţé àŕé ŕéđàçţéđ àš ţĥé ŕéçöŕđéŕ ŕéđàçţš ţĥéḿ, üñđéŕ ţĥé šàḿé ṽàüļţ ñàḿéš, ţĥé çĥàñĝé šéţ îš ļéƒţ öüţ, àñđ workhome.Home þüţš ţĥé öŕîĝîñàļš ƃàçķ ƒŕöḿ ţĥé þŕöĵéçţ ṽàüļţ ŵĥéŕé îţ ŕéàđš à ŕöŵ; à þöļîçý ţĥàţ đéţéçţš éñţîţîéš ŕéƒüšéš ţĥé ŵŕîţé. Ţĥé öþéŕàţîöñ'š subject çöļüḿñ ĥöļđš <doc key>@<edition>, àñđ ţĥé àđđŕéšš àđđš workspace, ţĥé éđîţîöñ, ţĥé ƃàšé àñđ ţĥé çàüšé ţö ŵĥàţ îţ çöṽéŕš, šö ţŵö ḿàçĥîñéš ţĥàţ ŕéƃàšé öñé ŵŕîţé öñţö öñé ĥéàđ ŕéçöŕđ öñé öþéŕàţîöñ. workhome.Home àñđ ţĥé þŕöĵéçţöŕ àþþéñđ îţ ŵîţĥ LocalBackend.RecordIf: ţĥé šàḿé ÎḾḾÉĐÎÀŢÉ ţŕàñšàçţîöñ àš Record, ŵĥîçĥ ƒîŕšţ ŕéàđš COALESCE(MAX(seq), 0) öṽéŕ (project, subject) ţĥŕöüĝĥ ţĥé þàŕţîàļ îñđéẋ idx_workspace_ops_subject àñđ àþþéñđš ñöţĥîñĝ ŵĥéñ îţ đéŕš ƒŕöḿ ţĥé ĥéàđ ţĥé ŵŕîţéŕ ŕéàđ (workspace.HeadMovedError). Ţĥé ŵŕîţéŕ ŕéàđš ţĥàţ ĥéàđ ŵîţĥ SubjectHead ƃéƒöŕé ţĥé þŕöĵéçţöŕ çàţçĥéš üþ.

Ţĥé þŕöĵéçţöŕ ƒöļđš ţĥöšé öþéŕàţîöñš îñţö ţŵö ţàƃļéš:

ŢàƃļéĶéýĤöļđš
edition_headdoc, edition, blockrev; runs, ţĥé çàñöñîçàļ ŕüñ ĴŠÖÑ îñļîñé ŵĥéñ îţ îš àţ ḿöšţ 16 ĶîƂ; blob, ţĥé àđđŕéšš öƒ ţĥé ƃļöƃ ĥöļđîñĝ îţ; status; origin àš ĴŠÖÑ; basis; stamp; op, ţĥé ŵŕîţé ţĥàţ ļéƒţ ţĥé ŕöŵ
edition_subject_headdoc, editionpath, ŵĥéŕé ţĥé đöçüḿéñţ ŵàš àţ ţĥé ĥéàđ; op, ţĥé öþéŕàţîöñ ţĥé ĥéàđ îš àţ; last, ţĥé ļàŕĝéšţ öþéŕàţîöñ îđ ƒöļđéđ; divergent, à ĴŠÖÑ ļîšţ öƒ {op, blocks: [{block, before, after}], release} ƒöŕ ţĥé ŵŕîţéš ţĥàţ đîđ ñöţ àđṽàñçé ţĥé ĥéàđ àñđ ţĥàţ ñöţĥîñĝ ĥàš šéţţļéđ šîñçé

À ŵŕîţé ŵĥöšé base éǫüàļš edition_subject_head.op àđṽàñçéš ţĥé ĥéàđ: éàçĥ ƃļöçķ îţ çĥàñĝéđ îš ŵŕîţţéñ ţö edition_head, öŕ đéļéţéđ ƒöŕ àñ after öƒ absent. À cause ŕéḿöṽéš ţĥàţ ŵŕîţé ƒŕöḿ divergent, à release éḿþţîéš divergent, àñđ à þéŕšöñ'š öŕ àñ àĝéñţ'š ŵŕîţé ŕéḿöṽéš ţĥé ƃļöçķš îţ ŵŕöţé ƒŕöḿ éṽéŕý ŵŕîţé îñ divergent, đŕöþþîñĝ à ŵŕîţé ļéƒţ ŵîţĥ ñöñé. Àñý öţĥéŕ ŵŕîţé îš àþþéñđéđ ţö divergent. À ŵŕîţé ŵĥöšé îđ šöŕţš ƃéƒöŕé last àŕŕîṽéđ öüţ öƒ öŕđéŕ (ḿéŕĝéđ îñ ƒŕöḿ àñöţĥéŕ ļöĝ), šö ţĥé þŕöĵéçţöŕ šéļéçţš éṽéŕý öþéŕàţîöñ öñ ţĥé šüƃĵéçţ (OpQuery.Subject), ƒöļđš ţĥéḿ àĝàîñ îñ îđ öŕđéŕ (workhome.Fold) àñđ ŕéþļàçéš ţĥé šüƃĵéçţ'š ŕöŵš (workhome.Store.Replace). Ţĥé ŕüñš öƒ à ƒöŕéîĝñ ŵŕîţé àŕé ŕéàđ ƒŕöḿ îţš ƃļöƃ àš îţ îš ƒöļđéđ, šö à ŕéƃüîļđ ŵŕîţéš ţĥé ŕöŵš ţĥé ļîṽé ŵŕîţéš ļéƒţ. Ñéîţĥéŕ ţàƃļé ķééþš à ļöĝ þöšîţîöñ: à çĥéçķþöîñţ çàŕŕîéš ƃöţĥ, àñđ à þöšîţîöñ ŕéàđ ƒŕöḿ àñöţĥéŕ ḿàçĥîñé'š ļöĝ ŵöüļđ ḿéàñ ñöţĥîñĝ ĥéŕé.

À ŵŕîţé ţö à đöçüḿéñţ ţĥé ŵöŕķšþàçé ĥöḿé ķééþš ŵĥöļé (à ĶÞŽ'š šöüŕçé öþéñéđ ƒöŕ éđîţîñĝ) îš à content.edit ŵîţĥ "home": "workspace", ñö edition, àñđ à document ƒîéļđ: {"format", "blob"}, ţĥé ƒöŕḿàţ ţĥàţ ŕéàđš ţĥé đöçüḿéñţ àñđ ţĥé àđđŕéšš öƒ ţĥé ƃļöƃ ĥöļđîñĝ îţš ƃýţéš àƒţéŕ ţĥé ŵŕîţé, ŵĥîçĥ blobs ļîšţš ţöö. base îš ţĥé öþéŕàţîöñ ţĥé đöçüḿéñţ'š ĥéàđ ŵàš àţ, doc_before àñđ doc_after àŕé îţš ŕéṽîšîöñš (sha256: öṽéŕ ţĥé ƃýţéš), àñđ ţĥé ţŕàñšîţîöñš àŕé ţĥé éđîţîöñš ţĥé çĥàñĝé šéţ çĥàñĝéđ, àš à ŵŕîţé ţö à ƒîļé ŕéçöŕđš ţĥéḿ; ţĥé ŵŕîţé ţĥàţ öþéñš à đöçüḿéñţ çàŕŕîéš ñöñé. À þéŕšöñ'š öŕ àñ àĝéñţ'š ŵŕîţé àļšö ļîšţš îñ document.decided ţĥé ƃļöçķš îţ ŵŕöţé öŕ ķéþţ, éàçĥ {block, edition} ŵîţĥ edition éḿþţý ƒöŕ ţĥé đöçüḿéñţ'š öŵñ. À ŕéƃàšé öŕ à đîšçàŕđ öƒ à đîṽéŕĝéñţ ŵŕîţé ñàḿéš ţĥàţ ŵŕîţé îñ cause, ŕéçöŕđš ţĥé ĥéàđ'š ƃýţéš àĝàîñ, àñđ ļîšţš îñ document.contested ţĥé ƃļöçķš ţĥé ŕéƃàšé ļéƒţ ƒöŕ à þéŕšöñ, ñöñé ƒöŕ à đîšçàŕđ öŕ à ŕéƃàšé ţĥàţ çàŕŕîéđ éṽéŕý ƃļöçķ öṽéŕ. Ţĥé subject çöļüḿñ ĥöļđš document:<doc key>, àñđ ţĥé àđđŕéšš àđđš workspace, document, ţĥé ƃàšé, ƃöţĥ ŕéṽîšîöñš, ţĥé ƒöŕḿàţ àñđ ţĥé ƃļöƃ, àñđ ƒöŕ à ŵŕîţé ŵîţĥ à çàüšé, ţĥé çàüšé àñđ ţĥé çöñţéšţéđ ƃļöçķš. Ţĥé þŕöĵéçţöŕ ƒöļđš ţĥöšé öþéŕàţîöñš îñţö à ţĥîŕđ ţàƃļé:

ŢàƃļéĶéýĤöļđš
document_headkeypath, ţĥé ŕéƒéŕéñçé ţĥé ĥéàđ ŵàš ŵŕîţţéñ ţĥŕöüĝĥ; rev; format; blob; op, ţĥé öþéŕàţîöñ ţĥé ĥéàđ îš àţ; last, ţĥé ļàŕĝéšţ öþéŕàţîöñ îđ ƒöļđéđ; divergent, à ĴŠÖÑ ļîšţ öƒ {op, before, after, contested} ƒöŕ ţĥé ŵŕîţéš ţĥàţ đîđ ñöţ àđṽàñçé ţĥé ĥéàđ, contested ļîšţîñĝ ţĥé ƃļöçķš à ŕéƃàšé ļéƒţ

À ŵŕîţé ŵîţĥ à cause ļéàṽéš ţĥé ĥéàđ ŵĥéŕé îţ îš: îţ đŕöþš ţĥé đîṽéŕĝéñţ ŵŕîţé îţ ñàḿéš ŵĥéñ îţ ļîšţš ñöţĥîñĝ çöñţéšţéđ, àñđ öţĥéŕŵîšé šéţš ţĥàţ ŵŕîţé'š contested. Àñý öţĥéŕ ŵŕîţé ŵĥöšé base éǫüàļš op àđṽàñçéš ţĥé ĥéàđ, àñđ öñé ŵîţĥ àñöţĥéŕ ƃàšé îš àþþéñđéđ ţö divergent. À þéŕšöñ'š öŕ àñ àĝéñţ'š ŵŕîţé ţĥàţ àđṽàñçéš ţĥé ĥéàđ ŕéḿöṽéš ţĥé ƃļöçķš îţ đéçîđéđ ƒŕöḿ éṽéŕý contested ļîšţ àñđ đŕöþš à ŵŕîţé ļéƒţ ŵîţĥ ñöñé; à đîṽéŕĝéñţ ŵŕîţé ñöƃöđý ĥàš ŕéƃàšéđ šţàýš üñţîļ îţš ŕéƃàšé öŕ đîšçàŕđ. À ŵŕîţé ţĥàţ àŕŕîṽéš öüţ öƒ öŕđéŕ ƒöļđš ţĥé đöçüḿéñţ àĝàîñ ƒŕöḿ éṽéŕý öþéŕàţîöñ öñ îţš šüƃĵéçţ (workhome.FoldDocument, Store.ReplaceDocument).

Ţĥé þŕöĵéçţöŕ àļšö ŵŕîţéš öñé block_history_op ŕöŵ þéŕ öþéŕàţîöñ: îţš îđ (ţĥé þŕîḿàŕý ķéý), îţš çöñţéñţ àđđŕéšš (üñîǫüé) àñđ îţš đöçüḿéñţ, šö ţĥé àđđŕéšš îš šţöŕéđ öñçé þéŕ öþéŕàţîöñ ŕàţĥéŕ ţĥàñ öñ éàçĥ öƒ îţš ŕöŵš. Àñ öþéŕàţîöñ ţĥàţ àŕŕîṽéš ƒöŕ àñ àđđŕéšš àñöţĥéŕ öþéŕàţîöñ ĥöļđš ţàķéš îţš þļàçé, ţĥé öţĥéŕ'š ŕöŵš àñđ îţš block_history_op ŕöŵ ŕéḿöṽéđ ƒîŕšţ: ţĥàţ îš ţĥé öþéŕàţîöñ à ḿéŕĝé ķéþţ îñ þļàçé öƒ à ĥéļđ öñé ŵîţĥ ţĥé šàḿé àđđŕéšš (ţĥé öļđéŕ îđ, workspace.LocalBackend.Record), àñđ ţĥé ŕöŵš îţ ļéàṽéš àŕé ţĥé ŕöŵš à ŕéƃüîļđ ƒŕöḿ ţĥé ḿéŕĝéđ ļöĝ ŵŕîţéš.

Ŕüñš öƒ çöñšéçüţîṽé content.edit öþéŕàţîöñš àŕé ŵŕîţţéñ îñ öñé ţŕàñšàçţîöñ, ļîṽé àñđ îñ à ŕéƃüîļđ, ŵîţĥ öñé þŕéþàŕéđ šţàţéḿéñţ. À ŕöŵ ţĥàţ àŕŕîṽéš ƒöŕ à ķéý ţĥé ţàƃļé ĥöļđš îš ŵŕîţţéñ àĝàîñ ŵîţĥ ţĥé àŕŕîṽîñĝ ṽàļüéš, šö ţĥé šàḿé öþéŕàţîöñ àþþļîéđ ţŵîçé ŵŕîţéš ţĥé šàḿé ŕöŵš. Öþéŕàţîöñ îđš šöŕţ ƃý ţîḿé, šö "ḿöšţ ŕéçéñţ" îš ORDER BY op DESC, àñđ ŠǪĻîţé'š MAX() ŵîţĥ ƃàŕé çöļüḿñš ĝîṽéš ţĥé ļàţéšţ ŕöŵ þéŕ ƃļöçķ ƒöŕ history.Store.Priors îñ öñé šţàţéḿéñţ. history.Store.Latest ŕéàđš ţĥé ļàţéšţ ŕöŵ öƒ éàçĥ éđîţîöñ öƒ à đöçüḿéñţ, öñé þŕîḿàŕý-ķéý šééķ þéŕ éđîţîöñ. Ŵĥéŕé ţĥé ļàţéšţ ŕöŵ đîđ ñöţ ļéàṽé ţĥé ŕéṽîšîöñ àñ éđîţîöñ ĥöļđš (à ƃŕàñçĥ šŵîţçĥ ƃŕöüĝĥţ ƃàçķ àñöţĥéŕ), history.Store.Wrote ƒîñđš ţĥé ŕöŵ ţĥàţ đîđ, à ŕéçöŕđéđ ŵŕîţé ƃéƒöŕé àñ öƃšéŕṽéđ öñé, ŵĥîçĥ îš ĥöŵ çöṽéŕàĝé, à đéçîšîöñ, ţĥé ŕéṽîéŵ çöñţéẋţ àñđ à þüšĥ ƒîñđ ţĥé ŵŕîţé ƃéĥîñđ à ţŕàñšļàţîöñ; ţĥé šţàļéñéšš ĝàţé ŕéàđš ţĥé šöüŕçé àļöñé àñđ ţàķéš ţĥé ļàţéšţ ŕöŵ. À šéçöñđ îñđéẋ, (doc, op), šéŕṽéš ţĥé ŕéàđš öƒ à ŵĥöļé đöçüḿéñţ, àñđ à ţĥîŕđ, block_history_reached öñ (doc, block, edition, after, op), ţĥé àđđŕéšš ļööķüþš öƒ à ŕéçöŕđîñĝ, ţĥé Wrote ļööķüþš àñđ àñ öƃšéŕṽîñĝ ŕéàđ'š çĥéçķ öƒ ţĥé ŕéṽîšîöñš îţ ƒöüñđ.

Rebuild đéļéţéš éṽéŕý ŕöŵ öƒ ţĥé þŕöĵéçţîöñ ţàƃļéš, šķîþþîñĝ ţĥé ƑŢŠ5 šĥàđöŵ ţàƃļéš (éḿþţýîñĝ ţĥé ṽîŕţüàļ ţàƃļé éḿþţîéš ţĥéḿ), ŕéšéţš ţĥéîŕ sqlite_sequence éñţŕîéš šö àüţöîñçŕéḿéñţ îđš ŕéþéàţ, ñàŕŕöŵš éṽéŕý ŕüļé ŵĥöšé öŕîĝîñ îš ţĥé þŕöĵéçţ, àñđ ŕéþļàýš ţĥé þŕöĵéçţ'š öþéŕàţîöñš îñ îđ öŕđéŕ. Ŵĥéñ à çĥéçķþöîñţ šţàñđš îţ ļöàđš ţĥé çĥéçķþöîñţ'š ţàƃļéš ƒîŕšţ àñđ ŕéþļàýš öñļý ţĥé öþéŕàţîöñš ţĥé ļöĝ ŕéçéîṽéđ àƒţéŕ îţ. À çĥéçķþöîñţ'š ţàƃļéš àŕé ĴŠÖÑ Ļîñéš, öñé öƃĵéçţ þéŕ ŕöŵ ŵîţĥ éàçĥ çéļļ ţàĝĝéđ ƃý îţš ŠǪĻîţé ţýþé ({"i": 1}, {"s": "x"}, {"b": "<base64>"}), àñđ çàŕŕý ţĥé rowid öƒ éṽéŕý ţàƃļé ŵĥöšé ŕöŵš àŕé ñöţ ñüḿƃéŕéđ ƃý àñ ÎÑŢÉĜÉŔ ÞŔÎḾÀŔÝ ĶÉÝ. À ţàƃļé ŵĥöšé ļîñéš þàšš 1 ḾîƂ îš çüţ, àţ ļîñé ƃöüñđàŕîéš, îñţö þàŕţš öƒ àţ ḿöšţ 16 ḾîƂ, éàçĥ šţöŕéđ àš à ƃļöƃ àñđ ñàḿéđ îñ ţĥé çĥéçķþöîñţ'š ḿàñîƒéšţ (kpz.CheckpointMark.Parts, ţàƃļé àñđ ƃļöƃ, îñ ļöàđ öŕđéŕ) àñđ îñ ţĥé checkpoint.write þàýļöàđ'š blobs. À ţàƃļé ţĥàţ öñļý ĝŕöŵš îš çüţ àţ ţĥé šàḿé ļîñéš éàçĥ ţîḿé, šö šüççéššîṽé çĥéçķþöîñţš šĥàŕé îţš éàŕļîéŕ þàŕţš. workspace.Applier.CheckpointMark ŕéþöŕţš ţĥé þàŕţš, àñđ workspace.Sync ŵŕîţéš ţĥéḿ ţö blobs/ ƃéƒöŕé ţĥé çĥéçķþöîñţ öñ à þüšĥ àñđ ƒéţçĥéš ţĥéḿ ƃéƒöŕé îñšţàļļîñĝ îţ öñ à ƒîŕšţ þüļļ. À ŕéƃüîļđ ţĥàţ çàññöţ ļöàđ à çĥéçķþöîñţ éḿþţîéš ţĥé ţàƃļéš àĝàîñ, ŕéþļàýš ţĥé ŵĥöļé ļöĝ àñđ ŕéþöŕţš ţĥé çĥéçķþöîñţ üñđéŕ Failed; öñé ţĥàţ ḿééţš öþéŕàţîöñš öƒ à ķîñđ îñ projector.RetiredKinds çöüñţš ţĥéḿ üñđéŕ Retired.

Ḿéàšüŕéđ îñ þŕöçéšš öñ àñ Ḿ-šéŕîéš ļàþţöþ, 16 ĝöŕöüţîñé ŵŕîţéŕš (KAPI_MEASURE_OPLOG=1 go test -tags fts5 ./core/projector -run Measure -v):

ḾéàšüŕéŔéšüļţ
ŕéƃüîļđ: 13 000 éñţŕîéš ƒŕöḿ öñé ƃàţçĥ, 2 000 šîñĝļé-éñţŕý öþéŕàţîöñš, 1 000 šîñĝļé-çöñçéþţ öþéŕàţîöñš2.8 š
à çöñçéþţ öŕ àñ éñţŕý ŵŕîţţéñ ţĥŕöüĝĥ ţĥé þŕöĵéçţöŕ, 16 ŵŕîţéŕš, öṽéŕ à šţöŕé öƒ 13 000 éñţŕîéšþ50 141 ḿš, þ99 283 ḿš
ţĥé šàḿé ŵŕîţéš šţŕàîĝĥţ ţö ţĥé šţöŕéš, ñö ļöĝþ50 138 ḿš, þ99 342 ḿš
àñ àĝéñţ'š öƃšéŕṽàţîöñ (Ledger.Append, ŵĥîçĥ ŵŕîţéš ñö šţöŕé), 16 ŵŕîţéŕš, 13 000 öţĥéŕ öþéŕàţîöñšþ50 21 ḿš, þ99 31 ḿš
à đéçîšîöñ (WorkStore.Put ţĥŕöüĝĥ ţĥé ĵöüŕñàļ), 16 ŵŕîţéŕš, 13 000 đéçîšîöñš îñ ţĥé ļöĝþ50 5 ḿš, þ99 39 ḿš
13 000 đéçîšîöñš ŕéàđ îñ àš öñé îḿþöŕţ0.7 š
ŕéƃüîļđ öƒ ţĥöšé 13 000 đéçîšîöñš ƒŕöḿ ţĥé ļöĝ0.3 š
çĥéçķþöîñţ öƒ ţĥéḿ (10.6 ḾƂ) / ŕéƃüîļđ ƒŕöḿ ţĥé çĥéçķþöîñţ0.3 š / 0.4 š
à çöñṽéŕĝéñçé þàšš öƒ éđîţš: 400 content.edit öþéŕàţîöñš, 75 200 ĥàšĥ-öñļý ţŕàñšîţîöñš, à đöçüḿéñţ àţ à ţîḿé22.2 ḾƂ çàŕŕîéđ ƃý ţĥé öþéŕàţîöñš àñđ ţĥéîŕ ƃļöƃš; 2.0 š (0.027 ḿš à ţŕàñšîţîöñ), üñđéŕ à ḿàçĥîñé ļöàđ àṽéŕàĝé öƒ àƃöüţ 18
ţĥé šàḿé þàšš ŕéçöŕđéđ îñ öñé RecordEdits çàļļ, öṽéŕ à ĥîšţöŕý ĥöļđîñĝ ţĥé ƒîŕšţ1.8 š
àƒţéŕ ƃöţĥ þàššéšworkspace.db 17.7 ḾƂ, ţĥé çöñţéẋţ šţöŕé 85.8 ḾƂ (150 400 block_history ŕöŵš)
ŕéƃüîļđ öƒ ţĥé 800 éđîţš2.2 š
çĥéçķþöîñţ àƒţéŕ ƃöţĥ þàššéš / ŕéƃüîļđ ƒŕöḿ îţ4.3 š, à 0.2 ḾƂ ƒîļé àñđ 6 þàŕţš / 4.1 š
à ĝàţéđ þàšš'š đŕàƒţš ķéþţ îñ ţĥé ŵöŕķšþàçé ĥöḿé: 400 ŵŕîţéš, 75 200 đŕàƒţš ŵîţĥ ţĥéîŕ ŕüñš, ƃàšîš àñđ šţàḿþ62.5 ḾƂ çàŕŕîéđ; 15 ţö 26 š (0.20 ţö 0.35 ḿš à đŕàƒţ), öñé ƃļöƃ îñšéŕţ þéŕ đŕàƒţ, üñđéŕ à ļöàđ àṽéŕàĝé öƒ 6 ţö 9
éṽéŕý đŕàƒţ ḿàđé àĝàîñ / ţĥé šàḿé đŕàƒţš àĝàîñ, àš à šţéàđý þàšš18 ţö 23 š / 1.3 š, ñöţĥîñĝ ŕéçöŕđéđ
àƒţéŕ ţĥé ţŵö þàššéš ţĥàţ ŵŕîţéworkspace.db 82.2 ḾƂ, ţĥé çöñţéẋţ šţöŕé 126 ḾƂ
ŕéàđîñĝ éṽéŕý ķéþţ éđîţîöñ / ŕéƃüîļđ öƒ ţĥé 800 ŵŕîţéš / ŕéļéàšîñĝ éṽéŕý éđîţîöñ0.5 š / 8.2 ţö 8.6 š / 3.5 ţö 3.6 š

Ţĥé þŕöĵéçţöŕ àđđš àƃöüţ à ḿîļļîšéçöñđ ţö à šîñĝļé ŵŕîţé. Ţĥé ţàîļ üñđéŕ 16 ŵŕîţéŕš ƃéļöñĝš ţö ţĥé çöñţéñţ ḿéḿöŕý'š ŕöŵ-ƃý-ŕöŵ ƑŢŠ5 ḿàîñţéñàñçé đéšçŕîƃéđ ƃéļöŵ, ŵĥîçĥ ţĥé đîŕéçţ ŵŕîţéš šĥöŵ ĵüšţ ţĥé šàḿé.

Ĵöîñîñĝ àçŕöšš ţĥé ţŵö ƒîļéš​

projectdb.DB.Join ŕüñš à ƒüñçţîöñ öñ öñé çöññéçţîöñ ŵîţĥ ƃöţĥ ƒîļéš ṽîšîƃļé: ţĥé þŕöĵéçţîöñ àš main àñđ ţĥé çöñţéẋţ šţöŕé àţţàçĥéđ àš context (projectdb.ContextSchema).

SELECT DISTINCT bt.block_hash
FROM block_texts bt
JOIN context.tb_terms t ON instr(bt.text_lower, t.text_lower) > 0
WHERE t.concept_id = ?

Ţĥé çöññéçţîöñ çàŕŕîéš PRAGMA query_only=ON ƒöŕ ţĥé ļéñĝţĥ öƒ ţĥé çàļļ àñđ đéţàçĥéš öñ ţĥé ŵàý öüţ, šö ţĥé þööļéđ çöññéçţîöñ ĝöéš ƃàçķ àš îţ çàḿé. À ĵöîñ ŕéàđš. À ŵŕîţé šþàññîñĝ ƃöţĥ þööļš îš ţŵö ţŕàñšàçţîöñš, ŵĥîçĥ îš ŵĥý ţĥé đéçîšîöñ ļéđĝéŕ àñđ ţĥé çöñţéñţ ḿéḿöŕý šîţ îñ ţĥé šàḿé þööļ: ţĥé þàîŕîñĝ ţĥàţ ḿüšţ ƃé àţöḿîç îš à đéçîšîöñ àñđ ţĥé ŵöŕđîñĝ ţĥé çöñţéñţ ḿéḿöŕý ļéàŕñš ƒŕöḿ îţ.

Ţĥé ţĥŕéé šéţţîñĝš éṽéŕý þööļ îš öþéñéđ ŵîţĥ​

storage.ProjectOptions() îš ImmediateTx, SerializeWrites àñđ CrossProcessWrites ţöĝéţĥéŕ:

  • BEGIN IMMEDIATE öñ éṽéŕý ţŕàñšàçţîöñ. À đéƒéŕŕéđ ţŕàñšàçţîöñ ţĥàţ ŕéàđš ƃéƒöŕé îţ ŵŕîţéš ḿüšţ üþĝŕàđé îţš ļöçķ, àñđ ŠǪĻîţé ŕéƒüšéš à çöñţéñđéđ üþĝŕàđé îḿḿéđîàţéļý, ŵîţĥöüţ çöñšüļţîñĝ busy_timeout. Ţàķîñĝ ţĥé ŵŕîţé ļöçķ üþ ƒŕöñţ þüţš ţĥé ŵàîţ šöḿéŵĥéŕé ţĥé ƃüšý ĥàñđļéŕ àþþļîéš.
  • Àñ îñ-þŕöçéšš ƑÎƑÖ þéŕḿîţ (core/storage.writeGate) éṽéŕý ŵŕîţé ĥöļđš ƒöŕ îţš ŵĥöļé ļîƒé. ŠǪĻîţé'š ƃüšý ƃàçķöƒƒ ĥàš ñö ḿéḿöŕý öƒ ŵĥö ĥàš ŵàîţéđ ļöñĝéšţ: ḿéàšüŕéđ àţ đöĝƒööđ šçàļé, à đŕîþ öƒ šḿàļļ üñîţ-šţàţé ŵŕîţéš çöḿþļéţéđ 32 öƒ 2650 àţţéḿþţš àĝàîñšţ à šàţüŕàţîñĝ çöñţéñţ-ḿéḿöŕý ŵŕîţéŕ. Ţĥé þéŕḿîţ þŕéṽéñţš ţĥîš ŵŕîţéŕ šţàŕṽàţîöñ.
  • À çŕöšš-þŕöçéšš àđṽîšöŕý ļöçķ öñ <database>.lock, à šéþàŕàţé ƒîļé ƃéšîđé ţĥé đàţàƃàšé, ţàķéñ îñšîđé ţĥé þéŕḿîţ àñđ ŕéļéàšéđ ƃý ţĥé šàḿé Commit öŕ Rollback. Îţ îš flock öñ Üñîẋ àñđ LockFileEx öñ Ŵîñđöŵš, àñđ à ñö-öþ öñ à ƃüîļđ ŵîţĥ ñéîţĥéŕ. Ţĥé šéþàŕàţé ƒîļé àṽöîđš îñţéŕƒéŕéñçé ŵîţĥ ŠǪĻîţé'š ļöçķš öñ ţĥé đàţàƃàšé.

core/storage/write.go àþþļîéš ƃöţĥ: ExecContext, Exec, BeginTx àñđ Begin šĥàđöŵ ţĥé þŕöḿöţéđ *sql.DB ḿéţĥöđš àñđ ţàķé ţĥé ĝàţé àñđ ţĥéñ ţĥé ļöçķ. Ŕéàđš šţàý þŕöḿöţéđ àñđ àŕé ñéṽéŕ ĝàţéđ: üñđéŕ ŴÀĻ à ŕéàđéŕ ñéîţĥéŕ ƃļöçķš à ŵŕîţéŕ ñöŕ ŵàîţš ƒöŕ öñé.

Þéŕḿîţš àñđ ļöçķš àŕé þéŕ ƒîļé. À ļöñĝ ƃļöçķ-šţöŕé ţŕàñšàçţîöñ ļöçķš öñļý ţĥé þŕöĵéçţîöñ, àļļöŵîñĝ ŕéṽîéŵ đéçîšîöñš ţö ƃé ŵŕîţţéñ çöñçüŕŕéñţļý ţö ţĥé çöñţéẋţ šţöŕé.

Ţŵö çöñšéǫüéñçéš àţ ţĥé çàļļ šîţé:

  • À ƃļöçķ-šţöŕé šéššîöñ ƒŕöḿ Blocks() îš öñé ţŕàñšàçţîöñ öṽéŕ à ŵĥöļé þüŕĝé-àñđ-ŕéƒîļļ, šö îţ ĥöļđš ţĥé þŕöĵéçţîöñ'š þéŕḿîţ ƒŕöḿ Begin ţö Commit. À ŵŕîţé ţö ţĥé šàḿé þööļ îššüéđ ƒŕöḿ ţĥé ĝöŕöüţîñé ĥöļđîñĝ öñé îš à đéàđļöçķ, ŕéþöŕţéđ ŕàţĥéŕ ţĥàñ ĥüñĝ: storage.ErrWriteGateReentrant.
  • À šéçöñđ ķàþî þŕöçéšš öñ ţĥé šàḿé þŕöĵéçţ ǫüéüéš îñ ţĥé ķéŕñéļ ŕàţĥéŕ ţĥàñ îñ ŠǪĻîţé'š ƃàçķöƒƒ, ƒöŕ ƃöţĥ þööļš.

Ŵĥàţ ţĥé çöñţéñţîöñ ĥàŕñéšš ḿéàšüŕéđ​

scripts/contention-harness -mode=workspace ŕüñš ţĥé šĥàþé ţĥé šþļîţ çŕéàţéš: 16 àĝéñţ-šĥàþéđ ŵŕîţéŕ þŕöçéššéš, éàçĥ îñ à çĥéçķöüţ öƒ îţš öŵñ, ŵŕîţîñĝ šḿàļļ ţŕàñšàçţîöñš îñţö öñé šĥàŕéđ çöñţéẋţ šţöŕé; öñé đéšķţöþ-šĥàþéđ ŕéàđéŕ þöļļîñĝ îţ ƒöŕ çĥàñĝé; àñđ öñé ÇĻÎ-šĥàþéđ ŕüñ ĥöļđîñĝ à þüŕĝé-àñđ-ŕéƒîļļ ţŕàñšàçţîöñ öṽéŕ îţš öŵñ þŕöĵéçţîöñ. Éîĝĥţééñ öþéŕàţîñĝ-šýšţéḿ þŕöçéššéš, ƃéçàüšé àñ îñ-þŕöçéšš þéŕḿîţ çàñ öñļý öŕđéŕ ŵŕîţéŕš ţĥàţ šĥàŕé à ĥàñđļé.

Ƃàŕ: žéŕö ƒàîļéđ ŵŕîţéš àçŕöšš éṽéŕý šţŕéàḿ, àñđ þ99 üñđéŕ 50 ḿš ƒöŕ ţĥé šḿàļļ ŵŕîţéš àñ öƃšéŕṽàţîöñ àñđ à đéçîšîöñ ḿàķé.

Ḿéàšüŕéđ öṽéŕ 120 š àţ đöĝƒööđ šçàļé (75 000 ƃļöçķš, 20 000 çöñţéñţ-ḿéḿöŕý éñţŕîéš, 2 000 çöñçéþţš, 75 000 üñîţš), 16 àĝéñţš ŕéçöŕđîñĝ à đéçîšîöñ öñçé à šéçöñđ àñđ þŕöḿöţîñĝ ŵöŕđîñĝ îñţö ţĥé çöñţéñţ ḿéḿöŕý éṽéŕý ţéñţĥ ŕöüñđ:

Ŵöŕķļöàđöþšƒàîļéđþ50 ḿšþ95 ḿšþ99 ḿšḿàẋ ḿš
àĝéñţ: đéçîšîöñ þüţ189500.684.8030.1976.99
àĝéñţ: ŕéĝîšţéŕ îñ ŵöŕķšþàçé1600.330.530.530.53
àĝéñţ: çöñţéñţ-ḿéḿöŕý þŕöḿöţîöñ198033.1948.7890.98105.36
đéšķţöþ: þöļļ ƒöŕ çĥàñĝé599016.3625.4429.8933.47
ÇĻÎ: þŕöĵéçţîöñ þüŕĝé+ŕéƒîļļ11074.8193.2693.2693.26
ÇĻÎ: çöñţéẋţ ŵŕîţé11032.1344.0744.0744.07

Ţĥé ḿéàšüŕéđ þŕöĵéçţîöñ ţŕàñšàçţîöñš ţööķ 75–93 ḿš, ŵĥîļé àĝéñţ đéçîšîöñ ŵŕîţéš ḿéţ ţĥé þ99 ţàŕĝéţ. Çöñţéñţ-ḿéḿöŕý þŕöḿöţîöñ àñđ þŕöĵéçţîöñ ŵŕîţéš àŕé ŕéþöŕţéđ šéþàŕàţéļý ƒŕöḿ ţĥé ļàţéñçý ĝàţé ƒöŕ šḿàļļ çöñţéẋţ ŵŕîţéš.

Çöñţéñţ-ḿéḿöŕý ŵŕîţéš ĥàṽé àđđîţîöñàļ îñđéẋîñĝ çöšţš. memory.Add ḿàîñţàîñš ţĥé ƑŢŠ5 ţàƃļéš ŕöŵ ƃý ŕöŵ, àñđ îţ ĝŕöŵš ŵîţĥ ţĥé çöŕþüš: öñ ţĥîš šţöŕé, ŵîţĥ à šîñĝļé ŵŕîţéŕ àñđ ñöƃöđý éļšé öñ ţĥé ƒîļé, îţ çöšţš 32 ḿš àţ ţĥé ḿéđîàñ àñđ 47 ḿš àţ ţĥé 99ţĥ þéŕçéñţîļé. Ţĥé šîẋţééñ-þŕöçéšš ŕüñ àƃöṽé ḿéàšüŕéš 33 ḿš àñđ 89 ḿš, šö çöñţéñţîöñ àđđš àƃöüţ à ḿîļļîšéçöñđ ţö ţĥé ḿéđîàñ. Ĥöļđîñĝ ţĥàţ ŵŕîţé ţö à 50 ḿš ƃàŕ ŵöüļđ ḿéàšüŕé ƑŢŠ5 ŕàţĥéŕ ţĥàñ ţĥé ŵöŕķšþàçé. À çöñṽéŕĝé ŵöŕķéŕ ŵîţĥ éñţŕîéš îñ ĥàñđ šĥöüļđ üšé BulkAddWithStream, ŵĥîçĥ îš öñé ţŕàñšàçţîöñ ƒöŕ ţĥé ƃàţçĥ; àţ ţĥé đéçîšîöñ ŕàţé (-memory-every=1) ţĥé šţöŕé šàţüŕàţéš àñđ ţĥé ţàîļ ĝöéš ŵîţĥ îţ.

Çŕöšš-þŕöçéšš ļöçķîñĝ ŕéđüçéš ţàîļ ļàţéñçý. Ŵîţĥ ţĥé îñ-þŕöçéšš þéŕḿîţ àļöñé, šîẋţééñ àĝéñţš ŕéçöŕđéđ žéŕö ƒàîļéđ ŵŕîţéš ƃüţ à 66 ḿš þ99 àñđ à 778 ḿš ḿàẋîḿüḿ öñ à ŵŕîţé ŵĥöšé ḿéđîàñ ŵàš 0.45 ḿš. Ţĥé ţàîļ ŵàš busy_timeout ŕàţĥéŕ ţĥàñ ţĥé ŵöŕķ: à ŵŕîţéŕ ţĥàţ ļöšéš ţĥé ŕàçé šļééþš à ƒîẋéđ šţéþ öƒ ţĥé ƃàçķöƒƒ ļàđđéŕ (1, 2, 5, 10, 15, 20, 25, 25, 25, 50, 50, 100 ḿš) àñđ ŵàķéš ţö ţŕý àĝàîñ, šö à ļöçķ ţĥàţ ƒŕééđ à ḿîļļîšéçöñđ ļàţéŕ šţàýš üñţàķéñ ƒöŕ ţĥé ŕéšţ öƒ ţĥé šţéþ. Ŕéþļàçîñĝ ţĥé šļééþ ŵîţĥ à ķéŕñéļ ŵàîţ ţööķ ţĥàţ þ99 ţö 21 ḿš àñđ ţĥé ḿàẋîḿüḿ ţö 57 ḿš öñ ţĥé šàḿé çöñƒîĝüŕàţîöñ.

Ŕéàđîñĝ ƒŕöḿ à ŵŕîţé-ŕéšţŕîçţéđ šàñđƃöẋ​

À çĥéçķ ḿàý ŕüñ ŵĥéŕé îţ çàñ ŕéàđ ţĥé ŵöŕķšþàçé àñđ ñöţ ŵŕîţé îţ: à ŕéšţŕîçţéđ šàñđƃöẋ, à ŕéàđ-öñļý ḿöüñţ, à ŵöŕķšþàçé öŵñéđ ƃý àñöţĥéŕ àççöüñţ. Üñđéŕ ŴÀĻ ţĥàţ îš à ŵŕîţé, ƃéçàüšé ŠǪĻîţé çŕéàţéš ţĥé ŵŕîţé-àĥéàđ ļöĝ'š šĥàŕéđ-ḿéḿöŕý îñđéẋ ƃéšîđé ţĥé đàţàƃàšé öñ ţĥé ƒîŕšţ çöññéçţîöñ.

storage.OpenReadOnly àñšŵéŕš îţ îñ ţŵö šţéþš. Îţ ƒîŕšţ öþéñš ţĥé đàţàƃàšé ŵĥéŕé îţ îš, ŵîţĥ ţĥé ĵöüŕñàļ-ḿöđé šŵîţçĥ šķîþþéđ àñđ éṽéŕý çöññéçţîöñ çàŕŕýîñĝ PRAGMA query_only=ON. ΃ ŠǪĻîţé šţîļļ çàññöţ öþéñ îţ, ţĥé đàţàƃàšé àñđ îţš ļöĝ àŕé çöþîéđ ţö à ŵŕîţàƃļé ţéḿþöŕàŕý đîŕéçţöŕý àñđ ţĥé çöþý îš öþéñéđ, àñđ ţĥé çöþý îš đéļéţéđ ŵĥéñ ţĥé ĥàñđļé çļöšéš. Ţĥé ŵöŕķšþàçé ţĥéñ ŕéþöŕţš îţšéļƒ ŕéàđ-öñļý, àñšŵéŕš ŕéàđš, àñđ ŕéƒüšéš à ŵŕîţé ŵîţĥ workspace.ErrReadOnly ŕàţĥéŕ ţĥàñ ļöšîñĝ îţ šöḿéŵĥéŕé ţĥé çàļļéŕ çàññöţ šéé.

À šýñçĥŕöñîžéđ ƒöļđéŕ îš ŕéƒüšéđ​

workspace.CloudSyncedDir ḿàţçĥéš à ŵöŕķšþàçé ŕööţ à þàţĥ šéĝḿéñţ àţ à ţîḿé, çàšé-îñšéñšîţîṽéļý, àĝàîñšţ ţĥé ƒöļđéŕ ñàḿéš îÇļöüđ Đŕîṽé, Đŕöþƃöẋ, ÖñéĐŕîṽé àñđ Ĝööĝļé Đŕîṽé üšé. À þŕéƒîẋ ḿàţçĥ ĥàš ţö éñđ àţ à šþàçé, à ĥýþĥéñ öŕ àñ üñđéŕšçöŕé, šö OneDrive - Contoso ḿàţçĥéš àñđ OneDriveProjects đöéš ñöţ. Ţĥé ḿéššàĝé ñàḿéš ţĥé ƒöļđéŕ, ţĥé þŕöđüçţ àñđ ţĥé ŵàý öüţ, ŵĥîçĥ îš ţö šéţ KAPI_DATA_DIR ţö à đîŕéçţöŕý öüţšîđé îţ.

Àđöþţîöñ öüţ öƒ ţĥé éḿƃéđđéđ ļàýöüţ​

projectdb.Open àšķš ŵĥéţĥéŕ ţĥé çöñţéẋţ šţöŕé ĥöļđš àñý üšéŕ ţàƃļé àţ àļļ ƃéƒöŕé îţ ƃîñđš ţĥé šüƃšýšţéḿš, ƃéçàüšé ƃîñđîñĝ çŕéàţéš ţĥöšé ţàƃļéš. À ŵöŕķšþàçé šüþþļîéđ ŵîţĥ àñ éḿþţý çöñţéẋţ šţöŕé àñđ à þŕöĵéçţîöñ ţĥàţ šţîļļ çàŕŕîéš çöñţéẋţ ţàƃļéš îš àđöþţéđ.

Éṽéŕý çöñţéẋţ ŕöŵ ḿöṽéš, ƃéçàüšé ñöţĥîñĝ ŕéþŕöđüçéš öñé: ţĥé ţéŕḿš, ţĥé çöñţéñţ ḿéḿöŕý, ţĥé ṽöîçé þŕöƒîļéš àñđ éṽéŕý ŕéçöŕđ îñ ţĥé đéçîšîöñ ļéđĝéŕ àŕé ŕéàđ öüţ öƒ ţĥé öļđ šţöŕé àñđ ŕéçöŕđéđ îñ ţĥé ñéŵ öñé. Ţĥé öļđ šţöŕé'š öŵñ ḿîĝŕàţîöñ ŕüñš ƒîŕšţ, šö à þŕöĵéçţ ţĥàţ þŕéđàţéš ţĥé ļéđĝéŕ ĥàš îţš ŕöŵš çàŕŕîéđ îñţö öñé ƃéƒöŕé ţĥéý àŕé ŕéàđ.

Ŵĥàţ îš đŕöþþéđ àƒţéŕŵàŕđš îš çöḿþüţéđ ŕàţĥéŕ ţĥàñ ļîšţéđ. Àñ éḿþţý þŕöĵéçţîöñ îš ƃüîļţ îñ ḿéḿöŕý, îţš ţàƃļéš àŕé ŵĥàţ à þŕöĵéçţîöñ îš éñţîţļéđ ţö ĥöļđ, àñđ éṽéŕý öţĥéŕ ţàƃļé îñ ţĥé ƒîļé ƃéļöñĝéđ ţö à šüƃšýšţéḿ ţĥàţ ĥàš ḿöṽéđ öüţ. Ṽîŕţüàļ ţàƃļéš àŕé đŕöþþéđ ƒîŕšţ, šîñçé ţĥéý ţàķé ţĥéîŕ šĥàđöŵ ţàƃļéš ŵîţĥ ţĥéḿ. Ţĥé ŵĥöļé þàšš îš ƃéšţ-郃öŕţ: à þŕöĵéçţ ţĥàţ çàññöţ ƃé àđöþţéđ ķééþš ƃöţĥ çöþîéš àñđ ŵöŕķš ƒŕöḿ ţĥé çöñţéẋţ šţöŕé, ŵĥîçĥ kapi store import ƒîļļš ƒŕöḿ ţĥé çĥéçķöüţ'š öŵñ ƒîļéš.

Ŕéļàţéđ​