CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-fluidframework--runtime-utils

Collection of utility functions for Fluid Runtime operations including handle management, summary operations, and request parsing.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

runtime-factories.mddocs/

Runtime Factories ⚠️ Legacy API

Abstract base classes and helpers for implementing container runtime factories with standardized lifecycle management. These utilities provide a foundation for creating runtime factories that handle container initialization, loading, and lifecycle events.

⚠️ Legacy API Warning: The RuntimeFactoryHelper class is part of the legacy API surface and is only available via the /legacy import path. This API may be deprecated in future versions. Consider using modern runtime factory patterns from the main package exports.

Available APIs

RuntimeFactoryHelper ⚠️ Legacy API

Abstract base class that provides the standard implementation pattern for runtime factories, with hooks for customizing initialization behavior.

Import Path: @fluidframework/runtime-utils/legacy

⚠️ This is a legacy API that may change or be removed in future versions. Use with caution in production code.

/**
 * Helper base class for implementing runtime factories
 * @template T - The type of runtime to create, defaults to IContainerRuntime
 */
abstract class RuntimeFactoryHelper<T = IContainerRuntime> implements IRuntimeFactory {
  /** Get the IRuntimeFactory interface */
  get IRuntimeFactory(): this;
  
  /**
   * Main runtime instantiation method called by the container
   * @param context - The container context
   * @param existing - Whether this is loading an existing container (true) or creating new (false)
   * @returns Promise resolving to the created runtime
   */
  instantiateRuntime(context: IContainerContext, existing: boolean): Promise<IRuntime>;
  
  /**
   * Called at the start of initializing a container to create the container runtime instance
   * Must be implemented by subclasses to create the specific runtime type
   * @param context - The container context
   * @param existing - Whether this is loading an existing container
   * @returns Promise resolving to the runtime instance
   */
  abstract preInitialize(
    context: IContainerContext,
    existing: boolean
  ): Promise<IRuntime & T>;
  
  /**
   * Called the one time the container is created (not on subsequent loads)
   * Override to perform first-time initialization logic
   * @param runtime - The runtime instance that was created
   * @returns Promise that resolves when initialization is complete
   */
  instantiateFirstTime(runtime: T): Promise<void>;
  
  /**
   * Called every time the container runtime is loaded for an existing container
   * Override to perform load-time initialization logic
   * @param runtime - The runtime instance that was loaded
   * @returns Promise that resolves when initialization is complete
   */
  instantiateFromExisting(runtime: T): Promise<void>;
  
  /**
   * Called at the end of initializing a container
   * Override to perform final initialization steps
   * @param runtime - The runtime instance that has been initialized
   * @returns Promise that resolves when finalization is complete
   */
  hasInitialized(runtime: T): Promise<void>;
}

Usage Examples:

import { RuntimeFactoryHelper } from "@fluidframework/runtime-utils/legacy";
import { ContainerRuntime, IContainerRuntimeOptions } from "@fluidframework/container-runtime";

// Custom runtime factory implementation
class MyRuntimeFactory extends RuntimeFactoryHelper<ContainerRuntime> {
  constructor(
    private readonly registryEntries: NamedFluidDataStoreRegistryEntries,
    private readonly runtimeOptions?: IContainerRuntimeOptions
  ) {
    super();
  }
  
  // Required: Create the runtime instance
  async preInitialize(
    context: IContainerContext,
    existing: boolean
  ): Promise<IRuntime & ContainerRuntime> {
    const runtime = await ContainerRuntime.loadRuntime({
      context,
      registryEntries: this.registryEntries,
      existing,
      runtimeOptions: this.runtimeOptions,
    });
    
    return runtime;
  }
  
  // Optional: First-time container creation logic
  async instantiateFirstTime(runtime: ContainerRuntime): Promise<void> {
    console.log("Creating new container - setting up initial data stores");
    
    // Create default data stores
    await runtime.createDataStore("main-data-store");
    await runtime.createDataStore("settings-data-store");
    
    // Set up initial configuration
    const configDataStore = await runtime.createDataStore("config");
    const config = await configDataStore.entryPoint.get();
    await config.initialize({
      version: "1.0",
      created: new Date().toISOString()
    });
  }
  
  // Optional: Existing container load logic  
  async instantiateFromExisting(runtime: ContainerRuntime): Promise<void> {
    console.log("Loading existing container - performing migration checks");
    
    // Check for data migrations
    const configDataStore = await runtime.getDataStore("config");
    const config = await configDataStore.entryPoint.get();
    const currentVersion = await config.getVersion();
    
    if (needsMigration(currentVersion)) {
      await performMigration(runtime, currentVersion);
    }
  }
  
  // Optional: Final initialization logic
  async hasInitialized(runtime: ContainerRuntime): Promise<void> {
    console.log("Runtime initialization complete - setting up monitoring");
    
    // Set up telemetry and monitoring
    runtime.on("dispose", () => {
      console.log("Runtime disposed");
    });
    
    runtime.on("connected", () => {
      console.log("Runtime connected");
    });
    
    runtime.on("disconnected", () => {
      console.log("Runtime disconnected");
    });
  }
}

// Usage
const runtimeFactory = new MyRuntimeFactory(
  [
    ["my-data-store", Promise.resolve(MyDataStoreFactory)],
    ["settings-store", Promise.resolve(SettingsStoreFactory)]
  ],
  {
    summaryOptions: { summaryConfigOverrides: { state: "disabled" } },
    gcOptions: { gcAllowed: true }
  }
);

// The runtime factory can now be used with container loading
const container = await loader.createDetachedContainer(codeDetails);

Advanced Runtime Factory Patterns

// Multi-tenant runtime factory
class MultiTenantRuntimeFactory extends RuntimeFactoryHelper<ContainerRuntime> {
  constructor(
    private tenantId: string,
    private tenantConfig: TenantConfiguration
  ) {
    super();
  }
  
  async preInitialize(
    context: IContainerContext, 
    existing: boolean
  ): Promise<IRuntime & ContainerRuntime> {
    // Customize runtime options based on tenant
    const runtimeOptions: IContainerRuntimeOptions = {
      summaryOptions: this.tenantConfig.summaryOptions,
      gcOptions: this.tenantConfig.gcOptions,
      compressionOptions: this.tenantConfig.compressionOptions
    };
    
    return ContainerRuntime.loadRuntime({
      context,
      registryEntries: this.getRegistryForTenant(this.tenantId),
      existing,
      runtimeOptions
    });
  }
  
  async instantiateFirstTime(runtime: ContainerRuntime): Promise<void> {
    // Set up tenant-specific initial state
    await this.createTenantDataStores(runtime);
    await this.applyTenantPolicies(runtime);
  }
  
  async instantiateFromExisting(runtime: ContainerRuntime): Promise<void> {
    // Validate tenant access and apply updates
    await this.validateTenantAccess(runtime);
    await this.updateTenantPolicies(runtime);
  }
  
  private async createTenantDataStores(runtime: ContainerRuntime): Promise<void> {
    const tenantStores = this.tenantConfig.requiredDataStores;
    for (const storeConfig of tenantStores) {
      await runtime.createDataStore(storeConfig.type, storeConfig.id);
    }
  }
}

// Development/Production runtime factory
class EnvironmentAwareRuntimeFactory extends RuntimeFactoryHelper<ContainerRuntime> {
  constructor(
    private environment: "development" | "production",
    private baseRegistryEntries: NamedFluidDataStoreRegistryEntries
  ) {
    super();
  }
  
  async preInitialize(
    context: IContainerContext,
    existing: boolean
  ): Promise<IRuntime & ContainerRuntime> {
    const runtimeOptions = this.getRuntimeOptionsForEnvironment();
    const registryEntries = this.getRegistryEntriesForEnvironment();
    
    return ContainerRuntime.loadRuntime({
      context,
      registryEntries,
      existing,
      runtimeOptions
    });
  }
  
  async hasInitialized(runtime: ContainerRuntime): Promise<void> {
    if (this.environment === "development") {
      // Add development-only debugging and logging
      this.setupDevelopmentTooling(runtime);
    } else {
      // Add production monitoring and telemetry
      this.setupProductionMonitoring(runtime);
    }
  }
  
  private getRuntimeOptionsForEnvironment(): IContainerRuntimeOptions {
    if (this.environment === "development") {
      return {
        summaryOptions: { summaryConfigOverrides: { state: "disabled" } },
        gcOptions: { gcAllowed: false }, // Disable GC in dev for easier debugging
        compressionOptions: { minimumBatchSizeInBytes: 0 } // No compression in dev  
      };
    } else {
      return {
        summaryOptions: { summaryConfigOverrides: { state: "enabled" } },
        gcOptions: { gcAllowed: true },
        compressionOptions: { minimumBatchSizeInBytes: 1024 }
      };
    }
  }
}

// Testing-focused runtime factory
class TestRuntimeFactory extends RuntimeFactoryHelper<ContainerRuntime> {
  private testHooks: TestHooks[] = [];
  
  addTestHook(hook: TestHook): void {
    this.testHooks.push(hook);
  }
  
  async preInitialize(
    context: IContainerContext,
    existing: boolean
  ): Promise<IRuntime & ContainerRuntime> {
    // Create runtime with test-friendly options
    const runtime = await ContainerRuntime.loadRuntime({
      context,
      registryEntries: this.getTestRegistryEntries(),
      existing,
      runtimeOptions: {
        summaryOptions: { summaryConfigOverrides: { state: "disabled" } },
        gcOptions: { gcAllowed: false }
      }
    });
    
    // Apply test hooks
    for (const hook of this.testHooks) {
      hook.apply(runtime);
    }
    
    return runtime;
  }
  
  async instantiateFirstTime(runtime: ContainerRuntime): Promise<void> {
    // Create predictable test data
    await this.createTestDataStores(runtime);
  }
  
  private async createTestDataStores(runtime: ContainerRuntime): Promise<void> {
    // Create data stores with known IDs for testing
    await runtime.createDataStore("test-store-1", "test-1");
    await runtime.createDataStore("test-store-2", "test-2");
  }
}

docs

compatibility-management.md

datastore-operations.md

garbage-collection.md

handle-management.md

index.md

runtime-factories.md

storage-utilities.md

summary-management.md

telemetry-utilities.md

tile.json