squadron 7.4.2
squadron: ^7.4.2 copied to clipboard
Multithreading and worker thread pool for Dart / Flutter, to offload CPU-bound and heavy I/O tasks to Isolate or Web Worker threads.
|
|
Squadron - Multithreading and worker pools in Dart #Offload CPU-bound and long running tasks and give your apps some air! |
🚀 Why Squadron? #
Dart is single-threaded by nature. While Isolate.run() is great for one-off tasks, it creates overhead for frequent operations. Squadron provides:
- 🔄 Persistent Worker Pools: Keep workers alive and ready to process tasks instantly.
- 🌐 Seamless Web Support: Uniform API for Isolates (Native) and Web Workers (JS/Wasm).
- 🛡️ Type Safety: Automatic code generation ensures your thread boundaries are type-safe.
- 🚫 Cancellation: Gracefully cancel long-running tasks.
- 📡 Streaming: Native support for
Streamreturn types from workers.
🏗️ Architecture #
sequenceDiagram
autonumber
participant App as Main App (UI)
box rgb(40, 100, 200, 0.1) Squadron / Generated Code
participant Pool as HelloWorldWorkerPool/Worker
end
box rgb(0, 150, 0, 0.1) Background Thread
participant Service as User Service
end
App->>Pool: worker.hello('Squadron')
Pool->>Service: Assign Task (Marshaled)
activate Service
Note over Service: Executing on background Isolate/Web Worker
Service-->>Pool: Return Result (Unmarshaled)
deactivate Service
Pool-->>App: Future<String> Result
📖 Table of Contents #
- Getting Started
- Implementing a Service
- Generating Workers
- Running your Worker
- Web Support (JS & Wasm)
- Advanced Concepts
- Community & Credits
1. Getting Started #
Add Squadron to your dependencies and squadron_builder to your dev dependencies:
dependencies:
squadron: ^7.4.0
dev_dependencies:
build_runner:
squadron_builder: ^9.0.0
Run dart pub get to install.
2. Implementing a Service #
Create a class with the logic you want to run in the background. Use @SquadronService and @SquadronMethod annotations.
// file: hello_world.dart
import 'dart:async';
import 'package:squadron/squadron.dart';
import 'hello_world.activator.g.dart';
part 'hello_world.worker.g.dart';
@SquadronService(baseUrl: '~/workers', targetPlatform: TargetPlatform.all)
base class HelloWorld {
@SquadronMethod()
FutureOr<String> hello([String? name]) {
name = name?.trim() ?? 'World';
return 'Hello, $name!';
}
}
3. Generating Workers #
Squadron uses code generation to handle the boilerplate of thread communication. Run the following command:
dart run build_runner build
This creates HelloWorldWorker and HelloWorldWorkerPool. These classes implement the same interface as your service but proxy calls to background threads.
4. Running your Worker #
In your application, instantiate the worker and use it like a normal service.
Important
Always stop your workers. Failure to call worker.stop() will keep your program running indefinitely.
import 'hello_world.dart';
void main() async {
final worker = HelloWorldWorker();
try {
// Squadron starts the worker automatically on the first call
final message = await worker.hello('Squadron');
print(message);
} finally {
worker.stop(); // Clean up the background thread
}
}
🌍 Web Support (JS & Wasm) #
Squadron is designed for a "write once, run anywhere" experience. When targeting the web, you must compile your worker entry points:
# Compile to JavaScript
dart compile js ".\src\lib\hello_world.web.g.dart" -o "..\web\workers\hello_world.web.g.dart.js"
# Compile to Web Assembly
dart compile wasm ".\src\lib\hello_world.web.g.dart" -o "..\web\workers\hello_world.web.g.dart.wasm"
Squadron will automatically detect the runtime environment and choose the correct implementation.
🛠️ Advanced Concepts #
Data Transfer & Marshaling #
Because workers run in separate memory spaces, data must be serialized ("marshaled") to cross thread boundaries. While base types (Strings, Numbers, Lists, Maps) are handled automatically, custom objects require a SquadronMarshaler.
📖 Learn more: Data Transfer and Types & Marshaling Wiki
Exception Handling #
Exceptions thrown in a worker are caught, serialized, and re-thrown on the caller's side, preserving the stack trace and error information where possible.
📖 Learn more: Exception Management Wiki
Logging #
Debugging background workers can be tricky. Squadron provides mechanisms to forward log messages from workers back to the main thread's debugger or console.
📖 Learn more: Observability and Logging Wiki
Special Thanks #
- Saad Ardati for feedback on Flutter integration.
- Martin Fink for major improvements to Stream support.
- Klemen Tusar for the Chopper JSON decoder sample.
- James O'Leary for sponsorship and contributions.