@quadnix/octo 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +108 -21
- package/dist/app.type.d.ts +141 -22
- package/dist/app.type.js.map +1 -1
- package/dist/decorators/model.decorator.d.ts +3 -5
- package/dist/decorators/model.decorator.js +1 -6
- package/dist/decorators/model.decorator.js.map +1 -1
- package/dist/decorators/on-event.decorator.d.ts +2 -2
- package/dist/decorators/on-event.decorator.js.map +1 -1
- package/dist/decorators/resource.decorator.d.ts +50 -1
- package/dist/decorators/resource.decorator.js +38 -1
- package/dist/decorators/resource.decorator.js.map +1 -1
- package/dist/errors/schema.error.d.ts +8 -1
- package/dist/errors/schema.error.js +5 -1
- package/dist/errors/schema.error.js.map +1 -1
- package/dist/errors/terraform.error.d.ts +4 -3
- package/dist/errors/terraform.error.js +4 -3
- package/dist/errors/terraform.error.js.map +1 -1
- package/dist/errors/transaction.error.d.ts +32 -2
- package/dist/errors/transaction.error.js +22 -0
- package/dist/errors/transaction.error.js.map +1 -1
- package/dist/events/action.event.d.ts +8 -2
- package/dist/events/action.event.js +2 -2
- package/dist/events/action.event.js.map +1 -1
- package/dist/events/command.event.d.ts +43 -0
- package/dist/events/command.event.js +33 -0
- package/dist/events/command.event.js.map +1 -0
- package/dist/events/event.model.d.ts +7 -5
- package/dist/events/event.model.js +5 -3
- package/dist/events/event.model.js.map +1 -1
- package/dist/events/hook/commit.hook.event.d.ts +1 -1
- package/dist/events/hook/commit.hook.event.js.map +1 -1
- package/dist/events/hook/hook.event.d.ts +1 -1
- package/dist/events/hook/hook.event.js.map +1 -1
- package/dist/events/hook/model.hook.event.d.ts +1 -1
- package/dist/events/hook/model.hook.event.js.map +1 -1
- package/dist/events/hook/resource.hook.event.d.ts +1 -1
- package/dist/events/hook/resource.hook.event.js.map +1 -1
- package/dist/events/index.d.ts +2 -0
- package/dist/events/index.js +2 -0
- package/dist/events/index.js.map +1 -1
- package/dist/events/mode-result.event.d.ts +1 -1
- package/dist/events/mode-result.event.js.map +1 -1
- package/dist/events/mode.event.d.ts +8 -4
- package/dist/events/mode.event.js.map +1 -1
- package/dist/events/module.event.d.ts +7 -3
- package/dist/events/module.event.js +3 -2
- package/dist/events/module.event.js.map +1 -1
- package/dist/events/registration.event.d.ts +1 -1
- package/dist/events/registration.event.js.map +1 -1
- package/dist/events/serialization.event.d.ts +1 -1
- package/dist/events/serialization.event.js.map +1 -1
- package/dist/events/state.event.d.ts +102 -0
- package/dist/events/state.event.js +69 -0
- package/dist/events/state.event.js.map +1 -0
- package/dist/events/terraform.event.d.ts +37 -1
- package/dist/events/terraform.event.js +24 -0
- package/dist/events/terraform.event.js.map +1 -1
- package/dist/events/transaction.event.d.ts +3 -3
- package/dist/events/transaction.event.js +1 -1
- package/dist/events/transaction.event.js.map +1 -1
- package/dist/functions/container/container.js +1 -1
- package/dist/functions/container/container.js.map +1 -1
- package/dist/functions/container/test-container.js +2 -2
- package/dist/functions/container/test-container.js.map +1 -1
- package/dist/functions/dependency/dependency.d.ts +9 -22
- package/dist/functions/dependency/dependency.js +5 -1
- package/dist/functions/dependency/dependency.js.map +1 -1
- package/dist/functions/diff/diff.d.ts +14 -7
- package/dist/functions/diff/diff.js.map +1 -1
- package/dist/functions/node/node-action.abstract.d.ts +8 -10
- package/dist/functions/node/node-action.abstract.js +10 -16
- package/dist/functions/node/node-action.abstract.js.map +1 -1
- package/dist/functions/node/node.abstract.js +21 -10
- package/dist/functions/node/node.abstract.js.map +1 -1
- package/dist/functions/node/node.interface.d.ts +2 -1
- package/dist/functions/schema/schema.js +1 -1
- package/dist/functions/schema/schema.js.map +1 -1
- package/dist/index.d.ts +8 -6
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/index.type.d.ts +5 -0
- package/dist/index.type.js +2 -0
- package/dist/index.type.js.map +1 -0
- package/dist/main.d.ts +4 -3
- package/dist/main.js +27 -11
- package/dist/main.js.map +1 -1
- package/dist/models/account/account.model.d.ts +6 -0
- package/dist/models/account/account.model.js +16 -0
- package/dist/models/account/account.model.js.map +1 -1
- package/dist/models/app/app.model.d.ts +0 -10
- package/dist/models/app/app.model.js +0 -30
- package/dist/models/app/app.model.js.map +1 -1
- package/dist/models/deployment/deployment.schema.d.ts +4 -0
- package/dist/models/deployment/deployment.schema.js +4 -0
- package/dist/models/deployment/deployment.schema.js.map +1 -1
- package/dist/models/environment/environment.model.d.ts +2 -2
- package/dist/models/environment/environment.model.js +2 -2
- package/dist/models/execution/execution.model.d.ts +1 -1
- package/dist/models/execution/execution.model.js +1 -1
- package/dist/models/image/image.model.d.ts +4 -3
- package/dist/models/image/image.model.js +7 -6
- package/dist/models/image/image.model.js.map +1 -1
- package/dist/models/model.abstract.js +1 -1
- package/dist/models/model.abstract.js.map +1 -1
- package/dist/models/pipeline/pipeline.model.d.ts +1 -1
- package/dist/models/pipeline/pipeline.model.js +1 -1
- package/dist/models/server/server.model.d.ts +2 -2
- package/dist/models/server/server.model.js +2 -2
- package/dist/models/service/service.model.d.ts +28 -11
- package/dist/models/service/service.model.js +56 -16
- package/dist/models/service/service.model.js.map +1 -1
- package/dist/models/service/service.schema.d.ts +46 -2
- package/dist/models/service/service.schema.js +54 -2
- package/dist/models/service/service.schema.js.map +1 -1
- package/dist/modes/commit.mode.d.ts +2 -2
- package/dist/modes/commit.mode.js +2 -2
- package/dist/modes/generate.mode.d.ts +2 -1
- package/dist/modes/generate.mode.js +3 -2
- package/dist/modes/generate.mode.js.map +1 -1
- package/dist/modes/run-action.mode.d.ts +1 -1
- package/dist/modes/run-action.mode.js +1 -1
- package/dist/modes/validate.mode.d.ts +24 -0
- package/dist/modes/validate.mode.js +89 -11
- package/dist/modes/validate.mode.js.map +1 -1
- package/dist/modules/module.container.d.ts +7 -1
- package/dist/modules/module.container.js +41 -5
- package/dist/modules/module.container.js.map +1 -1
- package/dist/modules/test-module.container.js +35 -83
- package/dist/modules/test-module.container.js.map +1 -1
- package/dist/overlays/overlay.abstract.js +1 -1
- package/dist/overlays/overlay.abstract.js.map +1 -1
- package/dist/resources/resource-action.interface.d.ts +4 -2
- package/dist/resources/resource.abstract.d.ts +50 -8
- package/dist/resources/resource.abstract.js +63 -32
- package/dist/resources/resource.abstract.js.map +1 -1
- package/dist/resources/resource.interface.d.ts +0 -2
- package/dist/resources/resource.schema.d.ts +11 -1
- package/dist/resources/resource.schema.js +11 -1
- package/dist/resources/resource.schema.js.map +1 -1
- package/dist/services/event/event.service.d.ts +2 -2
- package/dist/services/event/event.service.js.map +1 -1
- package/dist/services/input/input.service.d.ts +30 -2
- package/dist/services/input/input.service.js +71 -4
- package/dist/services/input/input.service.js.map +1 -1
- package/dist/services/serialization/model/model-serialization.service.d.ts +4 -6
- package/dist/services/serialization/model/model-serialization.service.js +20 -17
- package/dist/services/serialization/model/model-serialization.service.js.map +1 -1
- package/dist/services/serialization/resource/resource-serialization.service.d.ts +7 -6
- package/dist/services/serialization/resource/resource-serialization.service.js +25 -12
- package/dist/services/serialization/resource/resource-serialization.service.js.map +1 -1
- package/dist/services/state-management/local.state-provider.d.ts +25 -9
- package/dist/services/state-management/local.state-provider.js +127 -21
- package/dist/services/state-management/local.state-provider.js.map +1 -1
- package/dist/services/state-management/remote.state-provider.d.ts +216 -0
- package/dist/services/state-management/remote.state-provider.js +645 -0
- package/dist/services/state-management/remote.state-provider.js.map +1 -0
- package/dist/services/state-management/state-management.service.d.ts +83 -40
- package/dist/services/state-management/state-management.service.js +130 -26
- package/dist/services/state-management/state-management.service.js.map +1 -1
- package/dist/services/state-management/state-provider.interface.d.ts +50 -9
- package/dist/services/state-management/state-provider.interface.js +14 -1
- package/dist/services/state-management/state-provider.interface.js.map +1 -1
- package/dist/services/state-management/terraform-state.service.d.ts +32 -9
- package/dist/services/state-management/terraform-state.service.js +64 -21
- package/dist/services/state-management/terraform-state.service.js.map +1 -1
- package/dist/services/state-management/test.state-provider.d.ts +11 -10
- package/dist/services/state-management/test.state-provider.js +35 -14
- package/dist/services/state-management/test.state-provider.js.map +1 -1
- package/dist/services/terraform/terraform.service.d.ts +57 -3
- package/dist/services/terraform/terraform.service.js +95 -8
- package/dist/services/terraform/terraform.service.js.map +1 -1
- package/dist/services/terraform/terraform.type.js +1 -1
- package/dist/services/terraform/terraform.type.js.map +1 -1
- package/dist/services/transaction/transaction.service.d.ts +29 -5
- package/dist/services/transaction/transaction.service.js +198 -34
- package/dist/services/transaction/transaction.service.js.map +1 -1
- package/dist/services/validation/validation.service.d.ts +2 -2
- package/dist/{functions → utilities}/diff/diff.utility.d.ts +2 -1
- package/dist/{functions → utilities}/diff/diff.utility.js +4 -3
- package/dist/utilities/diff/diff.utility.js.map +1 -0
- package/dist/utilities/file/file.utility.d.ts +6 -7
- package/dist/utilities/file/file.utility.js +13 -68
- package/dist/utilities/file/file.utility.js.map +1 -1
- package/dist/utilities/hcl/hcl.utility.d.ts +83 -16
- package/dist/utilities/hcl/hcl.utility.js +200 -27
- package/dist/utilities/hcl/hcl.utility.js.map +1 -1
- package/dist/utilities/http/http.utility.d.ts +57 -0
- package/dist/utilities/http/http.utility.js +98 -0
- package/dist/utilities/http/http.utility.js.map +1 -0
- package/dist/utilities/string/string.utility.d.ts +23 -3
- package/dist/utilities/string/string.utility.js +29 -3
- package/dist/utilities/string/string.utility.js.map +1 -1
- package/dist/utilities/terraform/terraform.utility.d.ts +70 -21
- package/dist/utilities/terraform/terraform.utility.js +255 -66
- package/dist/utilities/terraform/terraform.utility.js.map +1 -1
- package/dist/utilities/test-helpers/test-classes.d.ts +19 -0
- package/dist/utilities/test-helpers/test-classes.js +22 -0
- package/dist/utilities/test-helpers/test-classes.js.map +1 -1
- package/dist/utilities/test-helpers/test-models.d.ts +8 -1
- package/dist/utilities/test-helpers/test-models.js +25 -12
- package/dist/utilities/test-helpers/test-models.js.map +1 -1
- package/dist/utilities/test-helpers/test-modes.d.ts +1 -1
- package/dist/utilities/test-helpers/test-modes.js +36 -13
- package/dist/utilities/test-helpers/test-modes.js.map +1 -1
- package/dist/utilities/test-helpers/test-modules.d.ts +6 -0
- package/dist/utilities/test-helpers/test-modules.js +6 -0
- package/dist/utilities/test-helpers/test-modules.js.map +1 -1
- package/dist/utilities/test-helpers/test-overlays.d.ts +3 -1
- package/dist/utilities/test-helpers/test-overlays.js +8 -2
- package/dist/utilities/test-helpers/test-overlays.js.map +1 -1
- package/dist/utilities/test-helpers/test-resources.d.ts +4 -2
- package/dist/utilities/test-helpers/test-resources.js +22 -20
- package/dist/utilities/test-helpers/test-resources.js.map +1 -1
- package/package.json +7 -2
- package/dist/functions/diff/diff.utility.js.map +0 -1
- package/dist/services/state-management/file-app-lock.utility.d.ts +0 -43
- package/dist/services/state-management/file-app-lock.utility.js +0 -124
- package/dist/services/state-management/file-app-lock.utility.js.map +0 -1
- package/dist/services/state-management/local-encryption.state-provider.d.ts +0 -71
- package/dist/services/state-management/local-encryption.state-provider.js +0 -116
- package/dist/services/state-management/local-encryption.state-provider.js.map +0 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { type IStateProvider } from './state-provider.interface.js';
|
|
2
|
+
/**
|
|
3
|
+
* Keeps state in Octo's managed backend, so a team shares one store and no machine holds the only copy.
|
|
4
|
+
*
|
|
5
|
+
* A run reads and writes a state directory on disk, exactly as {@link LocalStateProvider} does, and
|
|
6
|
+
* the backend is kept in step with it:
|
|
7
|
+
*
|
|
8
|
+
* - {@link RemoteStateProvider.refreshState} brings the directory up to the newest sealed state, and
|
|
9
|
+
* is what `octo generate` plans against.
|
|
10
|
+
* - {@link RemoteStateProvider.lockApp} opens a new record for the run, refusing when the newest
|
|
11
|
+
* sealed state has moved since the directory was refreshed.
|
|
12
|
+
* - Every write under the lock lands in the directory and in the run's record before it returns, so
|
|
13
|
+
* a run that dies leaves a record somebody can finish from another machine.
|
|
14
|
+
* - {@link RemoteStateProvider.unlockApp} seals the record and releases the lock.
|
|
15
|
+
*
|
|
16
|
+
* Two files of the provider's own sit beside the state files and are never uploaded:
|
|
17
|
+
* `remote-state.lock` records the run the directory belongs to and is deleted when the lock is
|
|
18
|
+
* released, and `remote-state-upload.lock` makes the octo processes of one machine write to the
|
|
19
|
+
* backend one at a time and is deleted after every write.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* await octo.initialize(
|
|
24
|
+
* new RemoteStateProvider({
|
|
25
|
+
* appId: 'my-app',
|
|
26
|
+
* localStateDirectoryPath: './.octo',
|
|
27
|
+
* organizationId: 'my-organization',
|
|
28
|
+
* sessionId: process.env.OCTO_SESSION!,
|
|
29
|
+
* stateManagementServiceUrl: 'http://localhost:3619/state',
|
|
30
|
+
* }),
|
|
31
|
+
* );
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* @group Services/State Management
|
|
35
|
+
*
|
|
36
|
+
* @see Techniques for [State Providers](/docs/techniques/state-providers).
|
|
37
|
+
*/
|
|
38
|
+
export declare class RemoteStateProvider implements IStateProvider {
|
|
39
|
+
private readonly appId;
|
|
40
|
+
private readonly localStateDirectoryPath;
|
|
41
|
+
private readonly localStateProvider;
|
|
42
|
+
private readonly lockContext;
|
|
43
|
+
private readonly organizationId;
|
|
44
|
+
private readonly sessionId;
|
|
45
|
+
private readonly stateManagementServiceUrl;
|
|
46
|
+
/**
|
|
47
|
+
* @param options `organizationId` and `appId` name the app whose state this is, and `sessionId`
|
|
48
|
+
* is the session the run acts as. `stateManagementServiceUrl` is the backend service, including
|
|
49
|
+
* the prefix its routes sit behind. `localStateDirectoryPath` is the directory state files are
|
|
50
|
+
* written into. `lockContext` is what a blocked run is shown about the holder.
|
|
51
|
+
*/
|
|
52
|
+
constructor(options: {
|
|
53
|
+
appId: string;
|
|
54
|
+
localStateDirectoryPath: string;
|
|
55
|
+
lockContext?: string;
|
|
56
|
+
organizationId: string;
|
|
57
|
+
sessionId: string;
|
|
58
|
+
stateManagementServiceUrl: string;
|
|
59
|
+
});
|
|
60
|
+
/**
|
|
61
|
+
* The id of the lock currently held, or `undefined` when the app is unlocked.
|
|
62
|
+
*/
|
|
63
|
+
getAppLock(): Promise<string | undefined>;
|
|
64
|
+
/**
|
|
65
|
+
* Reads a state file.
|
|
66
|
+
*
|
|
67
|
+
* @throws {@link TransactionError} With the message `No state found!` when the file does not exist.
|
|
68
|
+
*/
|
|
69
|
+
getState(stateFileName: string): Promise<Buffer>;
|
|
70
|
+
/**
|
|
71
|
+
* Whether `lockId` is the lock currently held.
|
|
72
|
+
*
|
|
73
|
+
* @throws {@link TransactionError} With the message `Invalid lock ID!` when a different lock is held,
|
|
74
|
+
* and when `lockId` is held but was neither taken nor resumed in this state directory.
|
|
75
|
+
*/
|
|
76
|
+
isAppLocked(lockId: string): Promise<boolean>;
|
|
77
|
+
/**
|
|
78
|
+
* The names of the state files whose name starts with `prefix`.
|
|
79
|
+
*/
|
|
80
|
+
listStates(prefix: string): Promise<string[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Takes the app lock and opens the run's record with everything the state directory holds.
|
|
83
|
+
*
|
|
84
|
+
* With `lockId`, resumes the run already holding that lock instead - from any machine, as the
|
|
85
|
+
* account that took it or an organization administrator. The state directory is replaced with
|
|
86
|
+
* what that run wrote so far, its journal included, keeping this machine's journal files, which join
|
|
87
|
+
* the record, and every write after lands in its record. A run that wrote nothing is resumed from the
|
|
88
|
+
* newest sealed state, without that state's journal.
|
|
89
|
+
*
|
|
90
|
+
* @throws {@link AppLockError} When a lock is held, naming the id that holds it. When the newest
|
|
91
|
+
* sealed state moved since {@link RemoteStateProvider.refreshState} last ran. When `lockId` is
|
|
92
|
+
* given and is not held.
|
|
93
|
+
*/
|
|
94
|
+
lockApp(lockId?: string): ReturnType<IStateProvider['lockApp']>;
|
|
95
|
+
/**
|
|
96
|
+
* Brings the state directory up to the newest sealed state, which is what a run plans against.
|
|
97
|
+
*
|
|
98
|
+
* A directory an open run is still writing is left alone. A directory the backend holds nothing
|
|
99
|
+
* for is left alone too: that is a first run, or a project arriving from another provider, and the
|
|
100
|
+
* files on disk are the only copy there is. Journal files are neither replaced nor taken.
|
|
101
|
+
*/
|
|
102
|
+
refreshState(): Promise<{
|
|
103
|
+
commitId?: string;
|
|
104
|
+
previousCommitId?: string;
|
|
105
|
+
replaced: boolean;
|
|
106
|
+
}>;
|
|
107
|
+
/**
|
|
108
|
+
* Writes state files, deleting each one given no `data`, and then writes the run's record once for
|
|
109
|
+
* all of them when a run is open. A name holding `/` is the machine's own: it is written beneath
|
|
110
|
+
* the state directory and never reaches the record.
|
|
111
|
+
*
|
|
112
|
+
* @throws {@link TransactionError} When the backend would refuse a file's name, before anything is
|
|
113
|
+
* written. When the backend refuses the write, which is where the limits it holds the app to apply.
|
|
114
|
+
*/
|
|
115
|
+
saveStates(stateFiles: Parameters<IStateProvider['saveStates']>[0]): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Writes the directory into the run's record, seals it, and releases the app lock. Unlocking an app
|
|
118
|
+
* that is not locked is not an error.
|
|
119
|
+
*
|
|
120
|
+
* A write that failed earlier left the directory ahead of the record, so the record is written once
|
|
121
|
+
* more before it is sealed: a sealed record is what every machine plans against next.
|
|
122
|
+
*
|
|
123
|
+
* @throws {@link TransactionError} With the message `Invalid lock ID!` when a different lock is held.
|
|
124
|
+
* When the directory cannot be written into the record, keeping the lock held.
|
|
125
|
+
*/
|
|
126
|
+
unlockApp(lockId: string): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* The route this app's state and locks are read and written at.
|
|
129
|
+
*/
|
|
130
|
+
private appStateUrl;
|
|
131
|
+
/**
|
|
132
|
+
* The session this run acts as. Every route but the health check is behind it.
|
|
133
|
+
*/
|
|
134
|
+
private authorizationHeader;
|
|
135
|
+
/**
|
|
136
|
+
* Deletes the lock file. Deleting one that is not there is not an error.
|
|
137
|
+
*/
|
|
138
|
+
private deleteLockFile;
|
|
139
|
+
/**
|
|
140
|
+
* How long the lock has been held, as a short readable span. Undefined when the recorded time
|
|
141
|
+
* cannot be read as one, so a broken value is left out rather than reported as a negative age.
|
|
142
|
+
*/
|
|
143
|
+
private describeAge;
|
|
144
|
+
/**
|
|
145
|
+
* Writes the directory into the run's record, when this directory belongs to an open run.
|
|
146
|
+
*/
|
|
147
|
+
private pushRun;
|
|
148
|
+
/**
|
|
149
|
+
* Every lock the backend holds on this app, oldest first.
|
|
150
|
+
*/
|
|
151
|
+
private readAppLocks;
|
|
152
|
+
/**
|
|
153
|
+
* The lock file. Empty when there is none.
|
|
154
|
+
*/
|
|
155
|
+
private readLockFile;
|
|
156
|
+
/**
|
|
157
|
+
* The newest record the app holds, sealed or not, or `undefined` when it holds none.
|
|
158
|
+
*
|
|
159
|
+
* One run holds the whole app at a time, so records are opened in the order they are sealed.
|
|
160
|
+
*/
|
|
161
|
+
private readNewestState;
|
|
162
|
+
/**
|
|
163
|
+
* Releases a lock, sealing the record its commit names. False when the lock is not held.
|
|
164
|
+
*/
|
|
165
|
+
private releaseAppLock;
|
|
166
|
+
/**
|
|
167
|
+
* Replaces every state file in the directory with the ones a state body names, downloading each
|
|
168
|
+
* from its URL and checking it against its SHA-256, and returns the body. The directory's journal
|
|
169
|
+
* files are kept; with `takeJournal`, the body's are written beside them.
|
|
170
|
+
*
|
|
171
|
+
* Each file is streamed to a temporary file beside it, so a state is not bounded by memory.
|
|
172
|
+
*/
|
|
173
|
+
private replaceStateFiles;
|
|
174
|
+
/**
|
|
175
|
+
* Resumes the run holding `lockId` in this state directory.
|
|
176
|
+
*/
|
|
177
|
+
private resumeAppLock;
|
|
178
|
+
/**
|
|
179
|
+
* Every state file the directory holds, which is every file in it but the provider's two lock
|
|
180
|
+
* files and a write still in progress, and none of the directories a run writes beside them, such
|
|
181
|
+
* as a generated terragrunt folder.
|
|
182
|
+
*/
|
|
183
|
+
private stateFileNames;
|
|
184
|
+
/**
|
|
185
|
+
* Runs `body` while holding `remote-state-upload.lock`, so one write to the backend is in flight at
|
|
186
|
+
* a time across every octo process on this machine. The file is deleted when `body` returns, and
|
|
187
|
+
* one left by a process that is gone is taken over.
|
|
188
|
+
*/
|
|
189
|
+
private withUploadLock;
|
|
190
|
+
/**
|
|
191
|
+
* Writes the lock file.
|
|
192
|
+
*/
|
|
193
|
+
private writeLockFile;
|
|
194
|
+
/**
|
|
195
|
+
* Writes the directory into the run's record as it stands, and returns the SHA-256 of every file the
|
|
196
|
+
* record holds afterwards.
|
|
197
|
+
*
|
|
198
|
+
* A write is three requests: the upload is asked for naming every file and its digest, the files
|
|
199
|
+
* the backend does not already hold are PUT to the URLs it answered with, and the upload is
|
|
200
|
+
* claimed. A file that fails to upload stops the write before the claim, and a claim with a file
|
|
201
|
+
* missing is refused, so a write lands whole or not at all. An upload left unclaimed is thrown away by
|
|
202
|
+
* the backend at the next write or when the lock is released. A directory holding nothing writes
|
|
203
|
+
* nothing, since the backend holds no empty state.
|
|
204
|
+
*
|
|
205
|
+
* The files are hard linked into a snapshot directory first and streamed from there, so a state is
|
|
206
|
+
* not bounded by memory, and a file another process replaces meanwhile is uploaded as it was
|
|
207
|
+
* hashed: a write replaces a file by renaming over it, which leaves the linked one as it was.
|
|
208
|
+
*/
|
|
209
|
+
private writeRunState;
|
|
210
|
+
/**
|
|
211
|
+
* Writes one file into the state directory whole, from `data` or copied from `filePath`, so a process
|
|
212
|
+
* reading it never reads half of it. Replacing the file rather than writing into it is also what lets
|
|
213
|
+
* an upload freeze it with a hard link.
|
|
214
|
+
*/
|
|
215
|
+
private writeStateFile;
|
|
216
|
+
}
|