| 796 | } |
| 797 | |
| 798 | #moduleHandleFor(id: string): Promise<WorkspaceModuleBackendHandle> { |
| 799 | const cached = this.#moduleHandles.get(id); |
| 800 | if (cached) return Promise.resolve(cached); |
| 801 | const inflight = this.#connectingModuleHandles.get(id); |
| 802 | if (inflight) return inflight; |
| 803 | const backend = this.#moduleBackendsById.get(id); |
| 804 | if (!backend) { |
| 805 | return Promise.reject( |
| 806 | new Error(`Workspace backend ${JSON.stringify(id)} does not execute modules.`), |
| 807 | ); |
| 808 | } |
| 809 | const generation = this.#connectionGeneration; |
| 810 | let promise!: Promise<WorkspaceModuleBackendHandle>; |
| 811 | promise = withSpan( |
| 812 | this.#observer, |
| 813 | "workspace.connect", |
| 814 | { "workspace.backend.id": id, "workspace.backend.type": backend.type }, |
| 815 | () => |
| 816 | backend.connect({ |
| 817 | db: this.#db, |
| 818 | waitUntil: this.#waitUntil, |
| 819 | fs: this.#fs, |
| 820 | git: this.#gitFactory ? this.git : DISABLED_GIT_CLIENT, |
| 821 | artifacts: this.#artifacts, |
| 822 | }), |
| 823 | ) |
| 824 | .then(async (handle) => { |
| 825 | if (generation !== this.#connectionGeneration) { |
| 826 | await handle.close().catch(() => undefined); |
| 827 | throw new Error(`Workspace closed while backend ${JSON.stringify(id)} was connecting.`); |
| 828 | } |
| 829 | this.#moduleHandles.set(id, handle); |
| 830 | return handle; |
| 831 | }) |
| 832 | .finally(() => { |
| 833 | if (this.#connectingModuleHandles.get(id) === promise) { |
| 834 | this.#connectingModuleHandles.delete(id); |
| 835 | } |
| 836 | }); |
| 837 | this.#connectingModuleHandles.set(id, promise); |
| 838 | return promise; |
| 839 | } |
| 840 | |
| 841 | // Lazy backend connect. Concurrent callers for the same id |
| 842 | // share one in-flight promise. The resolved handle is cached |