MCPcopy Create free account
hub / github.com/cloudflare/computer / rebuildExecHandle

Function rebuildExecHandle

packages/computer/src/client.ts:70–176  ·  view source on GitHub ↗
(
  remote: RemoteExecHandle,
  known: { id?: string; backend?: string } = {},
)

Source from the content-addressed store, hash-verified

68// local handle. Both paths wait for command post-exit synchronization before
69// completing; result() also returns its synchronization counts.
70async function rebuildExecHandle<E extends ExecEncoding>(
71 remote: RemoteExecHandle,
72 known: { id?: string; backend?: string } = {},
73): Promise<WorkspaceRuntimeExecHandle<E>> {
74 const [id, backend] = await Promise.all([known.id ?? remote.id, known.backend ?? remote.backend]);
75 let claimed: "result" | "stream" | undefined;
76 let resultPromise: Promise<WorkspaceRuntimeResult<E>> | undefined;
77 let reader: ReadableStreamDefaultReader<WorkspaceRuntimeEvent<E>> | undefined;
78 const stream = new ReadableStream<WorkspaceRuntimeEvent<E>>(
79 {
80 // Lazy: don't call remote.stream() until the consumer actually
81 // pulls. A result()-only caller never starts the stream, so the
82 // stub's single handle is free for its run-and-wait path.
83 pull: async (controller) => {
84 if (claimed === "result") {
85 controller.error(
86 new Error(
87 "exec handle already consumed by result(): result() and streaming are exclusive",
88 ),
89 );
90 return;
91 }
92 if (reader === undefined) {
93 claimed = "stream";
94 const encoded = await remote.stream();
95 reader = decodeRuntimeEvents(encoded).getReader() as ReadableStreamDefaultReader<
96 WorkspaceRuntimeEvent<E>
97 >;
98 }
99 try {
100 const activeReader = reader;
101 if (!activeReader) throw new Error("runtime stream reader was not initialized");
102 const { value, done } = await activeReader.read();
103 if (done) {
104 activeReader.releaseLock();
105 reader = undefined;
106 controller.close();
107 return;
108 }
109 controller.enqueue(value);
110 } catch (error) {
111 reader?.releaseLock();
112 reader = undefined;
113 controller.error(error);
114 }
115 },
116 cancel: async (reason) => {
117 const activeReader = reader;
118 reader = undefined;
119 if (!activeReader) {
120 dispose();
121 return;
122 }
123 try {
124 await activeReader.cancel(reason);
125 } finally {
126 activeReader.releaseLock();
127 dispose();

Callers 1

getWorkspaceFunction · 0.85

Calls 11

decodeRuntimeEventsFunction · 0.85
allMethod · 0.80
disposeFunction · 0.70
errorMethod · 0.65
streamMethod · 0.65
getReaderMethod · 0.65
readMethod · 0.65
closeMethod · 0.65
cancelMethod · 0.65
resultMethod · 0.65
killMethod · 0.65

Tested by

no test coverage detected