MCPcopy
hub / github.com/coder/mux / createCoderUnarchiveHook

Function createCoderUnarchiveHook

src/node/runtime/coderLifecycleHooks.ts:128–248  ·  view source on GitHub ↗
(options: {
  coderService: CoderService;
  getArchiveBehavior: () => CoderWorkspaceArchiveBehavior;
  timeoutMs?: number;
  stoppingWaitTimeoutMs?: number;
  stoppingPollIntervalMs?: number;
})

Source from the content-addressed store, hash-verified

126}
127
128export function createCoderUnarchiveHook(options: {
129 coderService: CoderService;
130 getArchiveBehavior: () => CoderWorkspaceArchiveBehavior;
131 timeoutMs?: number;
132 stoppingWaitTimeoutMs?: number;
133 stoppingPollIntervalMs?: number;
134}): AfterUnarchiveHook {
135 const timeoutMs = options.timeoutMs ?? DEFAULT_START_TIMEOUT_MS;
136
137 return async ({ workspaceId, workspaceMetadata }): Promise<Result<void>> => {
138 const runtimeConfig = workspaceMetadata.runtimeConfig;
139 if (!isSSHRuntime(runtimeConfig) || !runtimeConfig.coder) {
140 return Ok(undefined);
141 }
142
143 const coder = runtimeConfig.coder;
144
145 // Important safety invariant:
146 // Only start Coder workspaces that mux created (dedicated workspaces). If the user connected
147 // mux to an existing Coder workspace, unarchiving in mux should *not* start their environment.
148 if (coder.existingWorkspace === true) {
149 return Ok(undefined);
150 }
151
152 const workspaceName = coder.workspaceName?.trim();
153 if (!workspaceName) {
154 return Ok(undefined);
155 }
156
157 if (options.getArchiveBehavior() !== "stop") {
158 return Ok(undefined);
159 }
160
161 let status = await options.coderService.getWorkspaceStatus(workspaceName, {
162 timeoutMs: DEFAULT_STATUS_TIMEOUT_MS,
163 });
164
165 // Unarchive can happen immediately after archive, while the Coder workspace is still
166 // transitioning through "stopping". Starting during that transition can fail, so we
167 // best-effort poll briefly until it reaches a terminal state.
168 if (status.kind === "ok" && status.status === "stopping") {
169 const waitTimeoutMs = options.stoppingWaitTimeoutMs ?? DEFAULT_STOPPING_WAIT_TIMEOUT_MS;
170 const pollIntervalMs = options.stoppingPollIntervalMs ?? DEFAULT_STOPPING_POLL_INTERVAL_MS;
171 const deadlineMs = Date.now() + waitTimeoutMs;
172
173 log.debug(
174 "Coder workspace is still stopping after mux unarchive; waiting briefly before starting",
175 {
176 workspaceId,
177 coderWorkspaceName: workspaceName,
178 waitTimeoutMs,
179 pollIntervalMs,
180 }
181 );
182
183 while (status.kind === "ok" && status.status === "stopping") {
184 const remainingMs = deadlineMs - Date.now();
185 if (remainingMs <= 0) {

Callers 2

constructorMethod · 0.90

Calls 9

isSSHRuntimeFunction · 0.90
OkFunction · 0.90
ErrFunction · 0.90
getArchiveBehaviorMethod · 0.80
getWorkspaceStatusMethod · 0.80
debugMethod · 0.80
startWorkspaceMethod · 0.80
sleepFunction · 0.70

Tested by

no test coverage detected