fromUrl static method
Future<StemApp>
fromUrl(
- String url, {
- StemModule? module,
- Iterable<
StemModule> modules = const [], - Iterable<
TaskHandler< tasks = const [],Object?> > - TaskRegistry? registry,
- Iterable<
StemStoreAdapter> adapters = const [], - StemStoreOverrides overrides = const StemStoreOverrides(),
- StemWorkerConfig workerConfig = const StemWorkerConfig(),
- RevokeStore? revokeStore,
- UniqueTaskCoordinator? uniqueTaskCoordinator,
- bool uniqueTasks = false,
- Duration uniqueTaskDefaultTtl = const Duration(minutes: 5),
- String uniqueTaskNamespace = 'stem:unique',
- bool requireRevokeStore = false,
- RetryStrategy? retryStrategy,
- Iterable<
Middleware> middleware = const [], - PayloadSigner? signer,
- RoutingRegistry? routing,
- TaskPayloadEncoderRegistry? encoderRegistry,
- TaskPayloadEncoder resultEncoder = const JsonTaskPayloadEncoder(),
- TaskPayloadEncoder argsEncoder = const JsonTaskPayloadEncoder(),
- Iterable<
TaskPayloadEncoder> additionalEncoders = const [], - StemStack? stack,
Creates an app from a single backend URL plus adapter wiring.
This helper resolves broker/backend factories via StemStack.fromUrl and can optionally auto-wire revoke and unique-task coordination stores.
Implementation
static Future<StemApp> fromUrl(
String url, {
StemModule? module,
Iterable<StemModule> modules = const [],
Iterable<TaskHandler<Object?>> tasks = const [],
TaskRegistry? registry,
Iterable<StemStoreAdapter> adapters = const [],
StemStoreOverrides overrides = const StemStoreOverrides(),
StemWorkerConfig workerConfig = const StemWorkerConfig(),
RevokeStore? revokeStore,
UniqueTaskCoordinator? uniqueTaskCoordinator,
bool uniqueTasks = false,
Duration uniqueTaskDefaultTtl = const Duration(minutes: 5),
String uniqueTaskNamespace = 'stem:unique',
bool requireRevokeStore = false,
RetryStrategy? retryStrategy,
Iterable<Middleware> middleware = const [],
PayloadSigner? signer,
RoutingRegistry? routing,
TaskPayloadEncoderRegistry? encoderRegistry,
TaskPayloadEncoder resultEncoder = const JsonTaskPayloadEncoder(),
TaskPayloadEncoder argsEncoder = const JsonTaskPayloadEncoder(),
Iterable<TaskPayloadEncoder> additionalEncoders = const [],
StemStack? stack,
}) async {
final needsUniqueLockStore =
uniqueTasks &&
uniqueTaskCoordinator == null &&
workerConfig.uniqueTaskCoordinator == null;
final needsRevokeStore =
requireRevokeStore &&
revokeStore == null &&
workerConfig.revokeStore == null;
final resolvedStack =
stack ??
StemStack.fromUrl(
url,
adapters: adapters,
overrides: overrides,
uniqueTasks: needsUniqueLockStore,
requireRevokeStore: needsRevokeStore,
);
final autoDisposers = <Future<void> Function()>[];
var resolvedUniqueTaskCoordinator =
uniqueTaskCoordinator ?? workerConfig.uniqueTaskCoordinator;
if (needsUniqueLockStore) {
final lockFactory = resolvedStack.lockStore;
if (lockFactory == null) {
throw StateError(
'Unique task coordination requested but lock store factory missing.',
);
}
final lockStore = await lockFactory.create();
resolvedUniqueTaskCoordinator = UniqueTaskCoordinator(
lockStore: lockStore,
defaultTtl: uniqueTaskDefaultTtl,
namespace: uniqueTaskNamespace,
);
autoDisposers.add(() async => lockFactory.dispose(lockStore));
}
var resolvedRevokeStore = revokeStore ?? workerConfig.revokeStore;
if (needsRevokeStore) {
final revokeFactory = resolvedStack.revokeStore;
if (revokeFactory == null) {
throw StateError('Revoke store required but no revoke factory found.');
}
final createdRevokeStore = await revokeFactory.create();
resolvedRevokeStore = createdRevokeStore;
autoDisposers.add(() async => revokeFactory.dispose(createdRevokeStore));
}
try {
final app = await create(
module: module,
modules: modules,
tasks: tasks,
registry: registry,
broker: resolvedStack.broker,
backend: resolvedStack.backend,
workerConfig: workerConfig,
revokeStore: resolvedRevokeStore,
uniqueTaskCoordinator: resolvedUniqueTaskCoordinator,
retryStrategy: retryStrategy,
middleware: middleware,
signer: signer,
routing: routing,
encoderRegistry: encoderRegistry,
resultEncoder: resultEncoder,
argsEncoder: argsEncoder,
additionalEncoders: additionalEncoders,
);
// Dispose auto-provisioned lock/revoke stores after worker shutdown and
// before backend/broker factories are disposed.
app._insertAutoDisposers(autoDisposers);
return app;
} on Object catch (error, stackTrace) {
// If app creation fails, release any auto-provisioned stores now to avoid
// leaking startup resources.
for (final disposer in autoDisposers.reversed) {
try {
await disposer();
} on Object {
// Keep the original startup error as the primary failure.
}
}
Error.throwWithStackTrace(error, stackTrace);
}
}