Skip to content

arch: Shared BridgeLifecycle mixin for init/dispose state management #142

@bbopen

Description

@bbopen

Overview

Multiple issues across NodeBridge, PyodideBridge, and HttpBridge relate to inconsistent init/dispose lifecycle handling. This tracking issue proposes a shared lifecycle mixin.

Related Issues

Proposed Architecture

State Machine

pending → initializing → ready
    ↓         ↓           ↓
  disposed  failed     disposed
              ↓
           pending (retry)

BridgeLifecycle Mixin

type LifecycleState = 'pending' | 'initializing' | 'ready' | 'failed' | 'disposed';

abstract class BridgeLifecycle {
  protected state: LifecycleState = 'pending';
  protected initPromise?: Promise<void>;
  protected initAbortController?: AbortController;

  async init(): Promise<void> {
    if (this.state === 'disposed') {
      throw new BridgeDisposedError('Bridge has been disposed');
    }
    if (this.state === 'ready') {
      return;
    }
    if (this.initPromise) {
      return this.initPromise;
    }
    
    this.state = 'initializing';
    this.initAbortController = new AbortController();
    
    this.initPromise = this.doInit(this.initAbortController.signal)
      .then(() => { this.state = 'ready'; })
      .catch((error) => {
        this.state = 'failed';
        this.initPromise = undefined; // Allow retry
        throw error;
      });
    
    return this.initPromise;
  }

  async dispose(): Promise<void> {
    if (this.state === 'disposed') return;
    
    this.state = 'disposed';
    this.initAbortController?.abort();
    this.initPromise = undefined;
    
    await this.doDispose();
  }

  protected abstract doInit(signal: AbortSignal): Promise<void>;
  protected abstract doDispose(): Promise<void>;
}

Acceptance Criteria

  • All bridges use consistent lifecycle state machine
  • Init failures allow retry (initPromise cleared)
  • Dispose cancels in-flight init operations
  • Post-dispose operations throw BridgeDisposedError
  • Late spawns blocked after dispose
  • All 6 related issues can be closed

Scope

This fix touches:

  • src/runtime/node.ts - NodeBridge
  • src/runtime/pyodide.ts - PyodideBridge
  • src/runtime/http.ts - HttpBridge
  • New: src/runtime/lifecycle.ts - shared mixin

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions