Skip to content

Conversation

@seefeldb
Copy link
Contributor

@seefeldb seefeldb commented May 28, 2025

This is a significant refactoring aimed at removing singletons and introducing a centralized Runtime object. This change enhances modularity, testability, and potentially concurrency by managing services like storage, scheduling, and recipe/module management through a dedicated runtime instance.

Here's a detailed summary of the PR:

Core Change: Introduction of Runtime and Removal of Singletons

The most fundamental change is the introduction of a Runtime class. This class now encapsulates services that were previously accessed via global singletons (e.g., storage, recipeManager, moduleMap, blobbyServerUrl, runtime for script execution).

  • Instantiation & Dependency Injection:

    • Instead of global objects, a Runtime instance is created and often passed into constructors of classes like CharmManager, BackgroundCharmService, or used directly where global singletons were previously called.
    • Configuration options like storageUrl, blobbyServerUrl, signer, consoleHandler, and errorHandlers are now passed into the Runtime constructor.
  • Service Access:

    • Access to storage operations now typically happens via runtime.storage instead of the global storage object.
    • Recipe management is done through runtime.recipeManager instead of a global recipeManager.
    • Module registration and access are handled by runtime.moduleRegistry.
    • Document creation and access (e.g., getDoc, getCell, getDocByEntityId) are often now methods on runtime or runtime.documentMap.
    • The global runtime.runSingle (for script execution) is replaced by runtime.harness.runSingle.
  • Blobby Server URL:

    • setBlobbyServerUrl is removed. The URL is now configured via RuntimeOptions when creating a Runtime instance.
    • getBlobbyServerUrl is also removed, with the URL presumably accessed via the runtime instance where needed (e.g., runtime.blobbyServerUrl).

Impact on Packages:

  • @commontools/runner:

    • The global storage object is removed. Operations are now on runtime.storage.
    • setBlobbyServerUrl and getBlobbyServerUrl are removed.
    • Global runtime (for script execution) is replaced by runtime.harness.
    • getCell, getDoc, getCellFromEntityId, getCellFromLink, getImmutableCell are refactored to be methods on Runtime or runtime.documentMap.
    • Scheduler functions (idle, onConsole, onError, schedule, unschedule, run (for actions), addEventHandler, queueEvent) are now methods on runtime.scheduler.
    • Built-in modules (fetchData, llm, map, ifElse, streamData) are now registered with the runtime.moduleRegistry and receive the runtime instance, allowing them to use runtime services like runtime.documentMap.getDoc and runtime.idle.
  • @commontools/charm:

    • CharmManager constructor now accepts a Runtime instance.
    • It uses runtime.storage, runtime.recipeManager, and runtime.runner (for runSynced, idle).
    • getIframeRecipe now takes charmManager to access runtime.recipeManager.
    • saveSpell also takes charmManager for similar reasons.
  • @commontools/builder:

    • The global createCell function has been removed from direct export and is now exposed via declare global. The actual implementation is expected to be injected by the runtime environment (e.g., createCellFactory in the runner's harness).
    • Tests are updated to use runtime.documentMap.getDoc or runtime.getImmutableCell.
  • @commontools/background-charm-service:

    • cast-admin.ts and main.ts instantiate and use Runtime for storage, blobby URL, and signer configuration.
    • BackgroundCharmService constructor and methods now take/use runtime instead of a storage instance.
    • worker.ts also initializes and uses a Runtime instance for its operations, including passing consoleHandler and errorHandler. Error handling logic (isErrorWithContext) is slightly adjusted due to how errors might be propagated.
  • @commontools/cli:

    • cast-recipe.ts, charm_demo.ts, and main.ts are updated to use the new Runtime for setting up storage, signer, and blobby URL, and for getting cells/docs.
  • @commontools/jumble (UI Package):

    • A new RuntimeProvider and useRuntime hook are introduced to provide the Runtime instance via React context.
    • Components like NetworkInspector and User now use useRuntime to get the runtime ID for useStorageBroadcast.
    • CharmsManagerProvider now uses useRuntime to pass the runtime to the CharmManager constructor.
    • setupIframe now accepts a runtime argument to use its scheduler and idle methods.
    • The main application entry point (main.tsx) initializes the Runtime and wraps the application with RuntimeProvider.
    • Hooks like useSuggestions and views like SpellbookLaunchView now get charmManager (which contains the runtime) to access runtime.recipeManager.
  • @commontools/toolshed (Server Package):

    • The server's entry point (index.ts) now initializes a global Runtime instance instead of just storage, configuring it with the signer and memory URL.
    • Google OAuth handlers now use the global runtime instance instead of the global storage. The helper getAuthCellAndStorage is refactored to getAuthCell and uses the global runtime.

Other Notable Changes:

  • Error Handling: Some adjustments in worker.ts for how error context (like space, charmId) is checked, as errors might be instances of Error directly rather than a specific custom error type with those properties always present.
  • Recipe ID Generation in CharmManager: Slight modification in charmId function in CharmManager to ensure the extracted ID is a string.
  • Test Updates: Numerous test files are updated to instantiate Runtime or use it for creating cells/docs and accessing services, reflecting the core refactoring.

Summary:

This PR introduces a major architectural shift by deprecating global singleton access for core services (storage, recipeManager, script runtime, etc.) and consolidating them under a new Runtime class. Instances of Runtime are created with necessary configurations (like API URLs and signers) and then injected into various managers and services (e.g., CharmManager, BackgroundCharmService). This refactoring significantly improves the codebase's structure by promoting dependency injection, which generally leads to more modular, testable, and maintainable code. It also provides a clear context for runtime operations, potentially simplifying future extensions and concurrent execution scenarios. The changes touch nearly every package, indicating a broad and fundamental improvement to the system's architecture.

@seefeldb seefeldb requested review from Copilot and jsantell May 28, 2025 19:15
@linear
Copy link

linear bot commented May 28, 2025

@cubic-dev-ai
Copy link
Contributor

cubic-dev-ai bot commented May 28, 2025

Your cubic subscription is currently inactive. Please reactivate your subscription to receive AI reviews and use cubic.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Refactor runner’s singleton storage and recipeManager into injectable Runtime instances across the codebase.

  • Components now use useRuntime instead of a global storage import for broadcasts.
  • CLI commands and CharmManager constructors accept a Runtime, replacing direct calls to global storage, idle, and recipeManager.
  • Tests and the builder package are updated to initialize and use Runtime methods (getDoc, getImmutableCell, idle, etc.), and builder exports are adjusted (notably createCell).

Reviewed Changes

Copilot reviewed 71 out of 71 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/jumble/src/components/User.tsx Switched from storage to useRuntime().storage
packages/jumble/src/components/NetworkInspector.tsx Similar runtime-based storage broadcasts
packages/html/test/html-recipes.test.ts Initialize and dispose Runtime, use runtime.documentMap
packages/cli/main.ts Instantiate Runtime, pass into CharmManager
packages/cli/cast-recipe.ts Same runtime injection for castRecipe
packages/charm/src/manager.ts Refactored all storage and recipeManager usages to this.runtime
packages/builder/src/index.ts Changed createCell export to a type-only export
packages/builder/src/built-in.ts Removed createCell implementation in favor of declare

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is looking great 🥳

@seefeldb seefeldb force-pushed the refactor-singletons-2 branch from fef829b to 44878d2 Compare May 28, 2025 20:23
@seefeldb seefeldb marked this pull request as ready for review May 28, 2025 22:15
@seefeldb seefeldb force-pushed the refactor-singletons-2 branch from 66a9645 to 24daf8d Compare May 29, 2025 16:52
@seefeldb seefeldb force-pushed the refactor-singletons-2 branch from 2771efa to ed8f99f Compare May 30, 2025 21:50
@seefeldb seefeldb merged commit e0d0d71 into main May 30, 2025
6 checks passed
@seefeldb seefeldb deleted the refactor-singletons-2 branch May 30, 2025 22:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants