- Added `test-browser-worker.html` to demonstrate threading with Web Workers in browser environments. - Added `test-fallback.html` to verify fallback functionality when threading is unavailable. - Created `THREADING.md` to document unified threading implementation, including Node.js Worker Threads, Web Workers, and fallback mechanisms. - Updated Node.js version requirement in `README.md` and `package.json` to `>=24.0.0` for compatibility with improved Worker Threads API. - Enhanced `workerUtils.ts` to implement threading with a worker pool for Node.js and added Web Worker execution logic for browsers. - Enabled environment-aware threading availability in `environment.ts`. - Updated `rollup.config.js` to include CLI configurations for streamlined builds. - Adjusted `.gitignore` to exclude test artifacts and package files. These changes provide comprehensive testing and documentation of threading functionality, improve cross-environment compatibility, and enhance developer workflows.
5.6 KiB
Brainy Threading Implementation
This document explains how Brainy's threading implementation works across different environments.
Overview
Brainy uses a unified threading approach that adapts to the environment it's running in:
- Node.js: Uses Worker Threads API (optimized for Node.js 24+)
- Browser: Uses Web Workers API
- Fallback: Executes on the main thread when neither Worker Threads nor Web Workers are available
This implementation ensures that compute-intensive operations (like embedding generation and vector calculations) can be performed efficiently without blocking the main thread, while maintaining compatibility across all environments.
Implementation Details
Environment Detection
Brainy automatically detects the environment it's running in:
// From unified.ts
export const environment = {
isBrowser: typeof window !== 'undefined',
isNode: typeof process !== 'undefined' && process.versions && process.versions.node,
isServerless: typeof window === 'undefined' &&
(typeof process === 'undefined' || !process.versions || !process.versions.node)
}
Additional environment detection functions are available in src/utils/environment.ts:
// Check if threading is available
export function isThreadingAvailable(): boolean {
return areWebWorkersAvailable() || areWorkerThreadsAvailable();
}
// Check if Web Workers are available (browser)
export function areWebWorkersAvailable(): boolean {
return isBrowser() && typeof Worker !== 'undefined';
}
// Check if Worker Threads are available (Node.js)
export function areWorkerThreadsAvailable(): boolean {
if (!isNode()) return false;
try {
require('worker_threads');
return true;
} catch (e) {
return false;
}
}
Thread Execution
The core of the threading implementation is the executeInThread function in src/utils/workerUtils.ts:
export function executeInThread<T>(fnString: string, args: any): Promise<T> {
if (environment.isNode) {
return executeInNodeWorker<T>(fnString, args)
} else if (environment.isBrowser && typeof window !== 'undefined' && window.Worker) {
return executeInWebWorker<T>(fnString, args)
} else {
// Fallback to main thread execution
try {
const fn = new Function('return ' + fnString)()
return Promise.resolve(fn(args) as T)
} catch (error) {
return Promise.reject(error)
}
}
}
This function:
- Checks if it's running in Node.js and uses Worker Threads if available
- Checks if it's running in a browser and uses Web Workers if available
- Falls back to executing on the main thread if neither is available
Node.js Implementation
For Node.js environments, Brainy uses the Worker Threads API with optimizations for Node.js 24:
function executeInNodeWorker<T>(fnString: string, args: any): Promise<T> {
// Implementation using Node.js Worker Threads
// Includes worker pool management for better performance
// Uses dynamic imports with the 'node:' protocol prefix
// ...
}
Key optimizations:
- Worker pool to reuse workers and minimize overhead
- Dynamic imports with the
node:protocol prefix - Error handling and cleanup
Browser Implementation
For browser environments, Brainy uses the Web Workers API:
function executeInWebWorker<T>(fnString: string, args: any): Promise<T> {
// Implementation using browser Web Workers
// Creates a blob URL for the worker code
// Handles message passing and error handling
// ...
}
Key features:
- Creates workers using Blob URLs
- Proper cleanup of resources (terminating workers and revoking URLs)
- Error handling
Fallback Mechanism
When neither Worker Threads nor Web Workers are available, Brainy falls back to executing on the main thread:
// Fallback to main thread execution
try {
const fn = new Function('return ' + fnString)()
return Promise.resolve(fn(args) as T)
} catch (error) {
return Promise.reject(error)
}
This ensures that Brainy works in all environments, even if threading is not available.
Usage
The threading implementation is used throughout Brainy, particularly for compute-intensive operations like embedding generation:
export function createThreadedEmbeddingFunction(
model: EmbeddingModel
): EmbeddingFunction {
const embeddingFunction = createEmbeddingFunction(model)
return async (data: any): Promise<Vector> => {
// Convert the embedding function to a string
const fnString = embeddingFunction.toString()
// Execute the embedding function in a thread
return await executeInThread<Vector>(fnString, data)
}
}
Testing
Two test scripts are provided to verify the threading implementation:
demo/test-browser-worker.html: Tests the threading implementation in a browser environmentdemo/test-fallback.html: Tests the fallback mechanism when threading is not available
To run these tests:
- Build the project:
npm run build - Start a local server:
npx http-server - Open the test pages in a browser:
Compatibility
The threading implementation has been tested and works in:
- Node.js 24+ (using Worker Threads)
- Modern browsers (using Web Workers):
- Chrome
- Firefox
- Safari
- Edge
- Environments without threading support (using fallback mechanism)
Conclusion
Brainy's threading implementation provides efficient execution of compute-intensive operations across all environments, with optimizations for Node.js 24 and modern browsers, and a fallback mechanism for environments where threading is not available.