WorkflowStorage
WorkflowStorage is the storage interface used by WorkflowEngine.
dart
abstract class WorkflowStorage {
WorkflowRepository get workflows;
WorkflowInstanceRepository get instances;
UserTaskInstanceRepository get userTaskInstances;
WorkflowEventRepository get events;
Future<T> transaction<T>(Future<T> Function() operation);
Future<void> initialize();
Future<void> dispose();
Future<bool> healthCheck();
Future<StorageStats> getStats();
}Storage keeps typed data models. It does not resolve executors or run workflows.
Repositories
| Getter | Repository | Model |
|---|---|---|
workflows | WorkflowRepository | WorkflowDefinition |
instances | WorkflowInstanceRepository | WorkflowInstance |
userTaskInstances | UserTaskInstanceRepository | UserTaskInstance |
events | WorkflowEventRepository | WorkflowEvent |
WorkflowRepository
dart
abstract class WorkflowRepository {
Future<WorkflowDefinition> create(WorkflowDefinition workflow);
Future<WorkflowDefinition> update(WorkflowDefinition workflow);
Future<WorkflowDefinition?> getById(String id);
Future<WorkflowDefinition?> getByCode(String code, {int? version});
Future<List<WorkflowDefinition>> getAllVersions(String code);
Future<List<WorkflowDefinition>> list({
int limit = 100,
int offset = 0,
bool activeOnly = true,
});
Future<List<WorkflowDefinition>> search(String query, {int limit = 100});
Future<bool> delete(String code, {int? version});
Future<bool> activate(String code, {int? version});
Future<bool> deactivate(String code, {int? version});
Future<bool> codeExists(String code);
Future<int> getNextVersion(String code);
}WorkflowDefinition is the persisted definition shape. Use engine.loadWorkflowDefinition(definition) to convert it into an executable Workflow.
WorkflowInstanceRepository
dart
abstract class WorkflowInstanceRepository {
Future<WorkflowInstance> create(WorkflowInstance instance);
Future<WorkflowInstance> update(WorkflowInstance instance);
Future<WorkflowInstance?> getById(String id);
Future<List<WorkflowInstance>> query(WorkflowInstanceQuery query);
Future<List<WorkflowInstance>> listByDefinition(
String workflowId, {
int limit = 100,
int offset = 0,
});
Future<List<WorkflowInstance>> listByStatus(
WorkflowStatus status, {
int limit = 100,
int offset = 0,
});
Future<List<WorkflowInstance>> listActive({int limit = 100, int offset = 0});
Future<List<WorkflowInstance>> getByCorrelationId(String correlationId);
Future<List<WorkflowInstance>> getChildInstances(String parentInstanceId);
Future<bool> updateStatus(String id, WorkflowStatus status);
Future<bool> mergeOutput(String id, Map<String, dynamic> output);
Future<bool> setVariable(String id, WorkflowVariable variable);
Future<bool> updateTokens(String id, List<WorkflowToken> tokens);
Future<bool> delete(String id);
Future<Map<WorkflowStatus, int>> countByStatus();
Future<List<WorkflowInstance>> getTimedOutInstances(DateTime now);
Future<List<WorkflowInstance>> getWaitingForSignal(String signalName);
Future<List<WorkflowInstance>> getStaleRunningInstances({
required Duration staleThreshold,
int limit = 100,
});
}UserTaskInstanceRepository
dart
abstract class UserTaskInstanceRepository {
Future<UserTaskInstance> create(UserTaskInstance task);
Future<UserTaskInstance> update(UserTaskInstance task);
Future<UserTaskInstance?> getById(String id);
Future<void> delete(String id);
Future<List<UserTaskInstance>> getByWorkflowInstanceId(
String workflowInstanceId,
);
Future<UserTaskInstance> complete(
String taskId,
String userId,
Map<String, dynamic> output,
);
Future<UserTaskInstance> cancel(String taskId);
Future<int> cancelByWorkflowInstanceId(String workflowInstanceId);
Future<List<UserTaskInstance>> getOverdue();
Future<int> expireOverdue();
Future<int> countPendingByWorkflowInstanceId(String workflowInstanceId);
Future<UserTaskInstance?> findActive({
required String workflowInstanceId,
required String nodeId,
});
Future<List<UserTaskInstance>> getByStatus(TaskStatus status);
Future<List<UserTaskInstance>> search({
String? workflowInstanceId,
String? assignedToUserId,
String? assignedToRoleId,
String? assignedToGroupId,
TaskStatus? status,
int limit = 100,
int offset = 0,
});
}User task completion should be followed by a workflow signal when the workflow is waiting for that task's node/signal.
WorkflowEventRepository
dart
abstract class WorkflowEventRepository {
Future<WorkflowEvent> append(WorkflowEvent event);
Future<List<WorkflowEvent>> appendAll(List<WorkflowEvent> events);
Future<WorkflowEvent?> getById(String id);
Future<List<WorkflowEvent>> getByWorkflowInstanceId(
String workflowInstanceId, {
List<WorkflowEventType>? eventTypes,
int? limit,
int? offset,
});
Future<List<WorkflowEvent>> query(WorkflowEventQuery query);
Future<WorkflowEvent?> getLatestByWorkflowInstanceId(String workflowInstanceId);
Future<List<WorkflowEvent>> getByNodeId(
String workflowInstanceId,
String nodeId,
);
Future<List<WorkflowEvent>> getByUserTaskId(String userTaskId);
Future<List<WorkflowEvent>> getByUserId(
String userId, {
int limit = 100,
int offset = 0,
});
Future<int> countByWorkflowInstanceId(String workflowInstanceId);
Future<Map<WorkflowEventType, int>> countByTypeForWorkflowInstance(
String workflowInstanceId,
);
Future<List<WorkflowEvent>> getSummary(String workflowInstanceId);
Future<int> deleteByWorkflowInstanceId(String workflowInstanceId);
Future<int> pruneOlderThan(DateTime cutoff);
}StorageStats
dart
class StorageStats {
const StorageStats({
required this.totalDefinitions,
required this.totalInstances,
required this.activeInstances,
this.storageSizeBytes,
this.additional = const {},
});
}Built-in Implementations
InMemoryStorage
dart
final storage = InMemoryStorage(
workflowLoader: () async => [template.buildDefinition()],
);Use it for tests, local demos, and editor simulation. It clears data on dispose.
SupabaseStorage
dart
final storage = SupabaseStorage(
client: supabaseClient,
config: const SupabaseStorageConfig(schema: 'elog'),
);Default Supabase tables:
| Table | Purpose |
|---|---|
elog.workflows | Workflow definitions. |
elog.workflow_instances | Runtime instances. |
elog.workflow_user_tasks | User task inbox records. |
elog.workflow_events | Event/audit log. |
Engine Setup
dart
final context = RegistryTypeResolver(
descriptors: [DefaultWorkflowDescriptor(), descriptor],
);
final engine = WorkflowEngine(
context: context,
storage: storage,
executionMode: ExecutionMode.production,
);
await engine.initialize();