tasker-engine 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +443 -0
- data/Rakefile +10 -0
- data/app/controllers/tasker/analytics_controller.rb +179 -0
- data/app/controllers/tasker/application_controller.rb +45 -0
- data/app/controllers/tasker/graphql_controller.rb +193 -0
- data/app/controllers/tasker/handlers_controller.rb +217 -0
- data/app/controllers/tasker/health_controller.rb +229 -0
- data/app/controllers/tasker/metrics_controller.rb +111 -0
- data/app/controllers/tasker/page_sort.rb +97 -0
- data/app/controllers/tasker/task_diagrams_controller.rb +30 -0
- data/app/controllers/tasker/tasks_controller.rb +123 -0
- data/app/controllers/tasker/workflow_steps_controller.rb +69 -0
- data/app/graphql/examples/all_tasks.graphql +22 -0
- data/app/graphql/examples/pending_tasks.graphql +23 -0
- data/app/graphql/tasker/graph_ql_types/annotation_type.rb +14 -0
- data/app/graphql/tasker/graph_ql_types/base_argument.rb +9 -0
- data/app/graphql/tasker/graph_ql_types/base_connection.rb +11 -0
- data/app/graphql/tasker/graph_ql_types/base_edge.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_enum.rb +9 -0
- data/app/graphql/tasker/graph_ql_types/base_field.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_input_object.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_interface.rb +14 -0
- data/app/graphql/tasker/graph_ql_types/base_object.rb +10 -0
- data/app/graphql/tasker/graph_ql_types/base_scalar.rb +9 -0
- data/app/graphql/tasker/graph_ql_types/base_union.rb +11 -0
- data/app/graphql/tasker/graph_ql_types/dependent_system_object_map_type.rb +18 -0
- data/app/graphql/tasker/graph_ql_types/dependent_system_type.rb +13 -0
- data/app/graphql/tasker/graph_ql_types/mutation_type.rb +16 -0
- data/app/graphql/tasker/graph_ql_types/named_step_type.rb +16 -0
- data/app/graphql/tasker/graph_ql_types/named_task_type.rb +14 -0
- data/app/graphql/tasker/graph_ql_types/named_tasks_named_step_type.rb +19 -0
- data/app/graphql/tasker/graph_ql_types/node_type.rb +12 -0
- data/app/graphql/tasker/graph_ql_types/query_type.rb +20 -0
- data/app/graphql/tasker/graph_ql_types/task_annotation_type.rb +17 -0
- data/app/graphql/tasker/graph_ql_types/task_interface.rb +17 -0
- data/app/graphql/tasker/graph_ql_types/task_type.rb +26 -0
- data/app/graphql/tasker/graph_ql_types/workflow_step_type.rb +154 -0
- data/app/graphql/tasker/graph_ql_types.rb +42 -0
- data/app/graphql/tasker/mutations/base_mutation.rb +13 -0
- data/app/graphql/tasker/mutations/cancel_step.rb +29 -0
- data/app/graphql/tasker/mutations/cancel_task.rb +29 -0
- data/app/graphql/tasker/mutations/create_task.rb +52 -0
- data/app/graphql/tasker/mutations/update_step.rb +36 -0
- data/app/graphql/tasker/mutations/update_task.rb +41 -0
- data/app/graphql/tasker/queries/all_annotation_types.rb +17 -0
- data/app/graphql/tasker/queries/all_tasks.rb +23 -0
- data/app/graphql/tasker/queries/base_query.rb +9 -0
- data/app/graphql/tasker/queries/helpers.rb +16 -0
- data/app/graphql/tasker/queries/one_step.rb +24 -0
- data/app/graphql/tasker/queries/one_task.rb +18 -0
- data/app/graphql/tasker/queries/tasks_by_annotation.rb +31 -0
- data/app/graphql/tasker/queries/tasks_by_status.rb +30 -0
- data/app/graphql/tasker/tasker_rails_schema.rb +52 -0
- data/app/jobs/tasker/application_job.rb +8 -0
- data/app/jobs/tasker/metrics_export_job.rb +252 -0
- data/app/jobs/tasker/task_runner_job.rb +224 -0
- data/app/models/tasker/annotation_type.rb +26 -0
- data/app/models/tasker/application_record.rb +70 -0
- data/app/models/tasker/dependent_system.rb +26 -0
- data/app/models/tasker/dependent_system_object_map.rb +64 -0
- data/app/models/tasker/diagram/edge.rb +106 -0
- data/app/models/tasker/diagram/flowchart.rb +137 -0
- data/app/models/tasker/diagram/node.rb +99 -0
- data/app/models/tasker/named_step.rb +41 -0
- data/app/models/tasker/named_task.rb +121 -0
- data/app/models/tasker/named_tasks_named_step.rb +82 -0
- data/app/models/tasker/step_dag_relationship.rb +65 -0
- data/app/models/tasker/step_readiness_status.rb +59 -0
- data/app/models/tasker/task.rb +424 -0
- data/app/models/tasker/task_annotation.rb +36 -0
- data/app/models/tasker/task_diagram.rb +332 -0
- data/app/models/tasker/task_execution_context.rb +29 -0
- data/app/models/tasker/task_namespace.rb +41 -0
- data/app/models/tasker/task_transition.rb +235 -0
- data/app/models/tasker/workflow_step.rb +461 -0
- data/app/models/tasker/workflow_step_edge.rb +94 -0
- data/app/models/tasker/workflow_step_transition.rb +434 -0
- data/app/serializers/tasker/annotation_type_serializer.rb +8 -0
- data/app/serializers/tasker/handler_serializer.rb +109 -0
- data/app/serializers/tasker/task_annotation_serializer.rb +32 -0
- data/app/serializers/tasker/task_serializer.rb +168 -0
- data/app/serializers/tasker/workflow_step_serializer.rb +27 -0
- data/app/services/tasker/analytics_service.rb +409 -0
- data/app/views/tasker/task/_diagram.html.erb +32 -0
- data/config/initializers/dry_struct.rb +11 -0
- data/config/initializers/statesman.rb +6 -0
- data/config/initializers/tasker_orchestration.rb +17 -0
- data/config/initializers/time_formats.rb +4 -0
- data/config/routes.rb +34 -0
- data/config/tasker/subscriptions/example_integrations.yml +67 -0
- data/config/tasker/system_events.yml +305 -0
- data/db/functions/calculate_dependency_levels_v01.sql +45 -0
- data/db/functions/get_analytics_metrics_v01.sql +137 -0
- data/db/functions/get_slowest_steps_v01.sql +82 -0
- data/db/functions/get_slowest_tasks_v01.sql +96 -0
- data/db/functions/get_step_readiness_status_batch_v01.sql +140 -0
- data/db/functions/get_step_readiness_status_v01.sql +139 -0
- data/db/functions/get_system_health_counts_v01.sql +108 -0
- data/db/functions/get_task_execution_context_v01.sql +108 -0
- data/db/functions/get_task_execution_contexts_batch_v01.sql +104 -0
- data/db/init/schema.sql +2277 -0
- data/db/migrate/20250701165431_initial_tasker_schema.rb +116 -0
- data/db/views/tasker_step_dag_relationships_v01.sql +69 -0
- data/docs/APPLICATION_GENERATOR.md +384 -0
- data/docs/AUTH.md +1780 -0
- data/docs/CIRCUIT_BREAKER.md +224 -0
- data/docs/DEVELOPER_GUIDE.md +2665 -0
- data/docs/EVENT_SYSTEM.md +637 -0
- data/docs/EXECUTION_CONFIGURATION.md +341 -0
- data/docs/FLOW_CHART.md +149 -0
- data/docs/HEALTH.md +542 -0
- data/docs/METRICS.md +731 -0
- data/docs/OPTIMIZATION_PLAN.md +1479 -0
- data/docs/OVERVIEW.md +552 -0
- data/docs/QUICK_START.md +270 -0
- data/docs/REGISTRY_SYSTEMS.md +373 -0
- data/docs/REST_API.md +632 -0
- data/docs/ROADMAP.md +221 -0
- data/docs/SQL_FUNCTIONS.md +1408 -0
- data/docs/TASK_DIAGRAM.md +252 -0
- data/docs/TASK_EXECUTION_CONTROL_FLOW.md +237 -0
- data/docs/TELEMETRY.md +795 -0
- data/docs/TROUBLESHOOTING.md +756 -0
- data/docs/TaskHandlerGenerator.html +255 -0
- data/docs/Tasker/Analysis/RuntimeGraphAnalyzer.html +907 -0
- data/docs/Tasker/Analysis/TemplateGraphAnalyzer.html +1236 -0
- data/docs/Tasker/Analysis.html +117 -0
- data/docs/Tasker/AnalyticsController.html +450 -0
- data/docs/Tasker/AnalyticsService/BottleneckAnalytics.html +816 -0
- data/docs/Tasker/AnalyticsService/PerformanceAnalytics.html +586 -0
- data/docs/Tasker/AnalyticsService.html +2221 -0
- data/docs/Tasker/AnnotationType.html +137 -0
- data/docs/Tasker/AnnotationTypeSerializer.html +124 -0
- data/docs/Tasker/ApplicationController.html +147 -0
- data/docs/Tasker/ApplicationJob.html +128 -0
- data/docs/Tasker/ApplicationRecord.html +378 -0
- data/docs/Tasker/Authentication/AuthenticationError.html +124 -0
- data/docs/Tasker/Authentication/ConfigurationError.html +124 -0
- data/docs/Tasker/Authentication/Coordinator.html +242 -0
- data/docs/Tasker/Authentication/Interface.html +560 -0
- data/docs/Tasker/Authentication/InterfaceError.html +124 -0
- data/docs/Tasker/Authentication/NoneAuthenticator.html +338 -0
- data/docs/Tasker/Authentication.html +119 -0
- data/docs/Tasker/Authorization/AuthorizationError.html +139 -0
- data/docs/Tasker/Authorization/BaseCoordinator.html +927 -0
- data/docs/Tasker/Authorization/ConfigurationError.html +153 -0
- data/docs/Tasker/Authorization/ResourceConstants/ACTIONS.html +428 -0
- data/docs/Tasker/Authorization/ResourceConstants/RESOURCES.html +365 -0
- data/docs/Tasker/Authorization/ResourceConstants.html +146 -0
- data/docs/Tasker/Authorization/ResourceRegistry.html +882 -0
- data/docs/Tasker/Authorization/UnauthorizedError.html +153 -0
- data/docs/Tasker/Authorization.html +582 -0
- data/docs/Tasker/CacheCapabilities.html +167 -0
- data/docs/Tasker/CacheStrategy.html +1297 -0
- data/docs/Tasker/Concerns/Authenticatable.html +116 -0
- data/docs/Tasker/Concerns/Authorizable/AdminStatusChecker.html +256 -0
- data/docs/Tasker/Concerns/Authorizable.html +816 -0
- data/docs/Tasker/Concerns/ControllerAuthorizable.html +157 -0
- data/docs/Tasker/Concerns/EventPublisher.html +4023 -0
- data/docs/Tasker/Concerns/IdempotentStateTransitions.html +806 -0
- data/docs/Tasker/Concerns/LifecycleEventHelpers.html +129 -0
- data/docs/Tasker/Concerns/OrchestrationPublisher.html +129 -0
- data/docs/Tasker/Concerns/StateMachineBase/ClassMethods.html +1075 -0
- data/docs/Tasker/Concerns/StateMachineBase/StateMachineBase/ClassMethods.html +191 -0
- data/docs/Tasker/Concerns/StateMachineBase/StateMachineBase.html +126 -0
- data/docs/Tasker/Concerns/StateMachineBase.html +153 -0
- data/docs/Tasker/Concerns/StructuredLogging.html +1413 -0
- data/docs/Tasker/Concerns.html +117 -0
- data/docs/Tasker/Configuration/AuthConfiguration.html +1023 -0
- data/docs/Tasker/Configuration/ConfigurationProxy.html +581 -0
- data/docs/Tasker/Configuration/DatabaseConfiguration.html +475 -0
- data/docs/Tasker/Configuration/EngineConfiguration.html +1265 -0
- data/docs/Tasker/Configuration/HealthConfiguration.html +791 -0
- data/docs/Tasker/Configuration/TelemetryConfiguration.html +1308 -0
- data/docs/Tasker/Configuration/TelemetryConfigurationProxy.html +388 -0
- data/docs/Tasker/Configuration.html +1669 -0
- data/docs/Tasker/ConfigurationError.html +143 -0
- data/docs/Tasker/ConfiguredTask.html +514 -0
- data/docs/Tasker/Constants/EventDefinitions.html +590 -0
- data/docs/Tasker/Constants/LifecycleEvents.html +137 -0
- data/docs/Tasker/Constants/ObservabilityEvents/Step.html +152 -0
- data/docs/Tasker/Constants/ObservabilityEvents/Task.html +142 -0
- data/docs/Tasker/Constants/ObservabilityEvents.html +126 -0
- data/docs/Tasker/Constants/RegistryEvents.html +285 -0
- data/docs/Tasker/Constants/StepEvents.html +177 -0
- data/docs/Tasker/Constants/TaskEvents.html +167 -0
- data/docs/Tasker/Constants/TaskExecution/ExecutionStatus.html +207 -0
- data/docs/Tasker/Constants/TaskExecution/HealthStatus.html +191 -0
- data/docs/Tasker/Constants/TaskExecution/RecommendedAction.html +207 -0
- data/docs/Tasker/Constants/TaskExecution.html +126 -0
- data/docs/Tasker/Constants/TaskFinalization/ErrorMessages.html +132 -0
- data/docs/Tasker/Constants/TaskFinalization/PendingReasons.html +207 -0
- data/docs/Tasker/Constants/TaskFinalization/ReenqueueReasons.html +239 -0
- data/docs/Tasker/Constants/TaskFinalization.html +126 -0
- data/docs/Tasker/Constants/TaskStatuses.html +223 -0
- data/docs/Tasker/Constants/TestEvents.html +163 -0
- data/docs/Tasker/Constants/WorkflowEvents.html +222 -0
- data/docs/Tasker/Constants/WorkflowStepStatuses.html +223 -0
- data/docs/Tasker/Constants.html +561 -0
- data/docs/Tasker/DependentSystem.html +137 -0
- data/docs/Tasker/DependentSystemObjectMap.html +250 -0
- data/docs/Tasker/DetectorRegistry.html +598 -0
- data/docs/Tasker/Diagram/Edge.html +1191 -0
- data/docs/Tasker/Diagram/Flowchart.html +1539 -0
- data/docs/Tasker/Diagram/Node.html +1165 -0
- data/docs/Tasker/Diagram.html +117 -0
- data/docs/Tasker/Engine.html +215 -0
- data/docs/Tasker/Error.html +139 -0
- data/docs/Tasker/Events/Bus.html +1226 -0
- data/docs/Tasker/Events/Catalog/CatalogPrinter.html +258 -0
- data/docs/Tasker/Events/Catalog/CustomEventRegistrar.html +276 -0
- data/docs/Tasker/Events/Catalog/ExamplePayloadGenerator.html +294 -0
- data/docs/Tasker/Events/Catalog.html +1291 -0
- data/docs/Tasker/Events/CustomRegistry.html +943 -0
- data/docs/Tasker/Events/DefinitionLoader.html +575 -0
- data/docs/Tasker/Events/EventPayloadBuilder/ErrorInfoExtractor.html +286 -0
- data/docs/Tasker/Events/EventPayloadBuilder/StepPayloadBuilder.html +312 -0
- data/docs/Tasker/Events/EventPayloadBuilder.html +664 -0
- data/docs/Tasker/Events/Publisher.html +365 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber/ErrorCategorizer/ErrorTypeClassifier.html +1128 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber/ErrorCategorizer.html +270 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber/MetricTagsExtractor.html +266 -0
- data/docs/Tasker/Events/Subscribers/BaseSubscriber.html +2556 -0
- data/docs/Tasker/Events/Subscribers/MetricsSubscriber.html +723 -0
- data/docs/Tasker/Events/Subscribers/TelemetrySubscriber.html +2251 -0
- data/docs/Tasker/Events/Subscribers.html +117 -0
- data/docs/Tasker/Events/SubscriptionLoader.html +493 -0
- data/docs/Tasker/Events.html +294 -0
- data/docs/Tasker/EventsGenerator.html +459 -0
- data/docs/Tasker/Functions/FunctionBasedAnalyticsMetrics/AnalyticsMetrics.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedAnalyticsMetrics.html +412 -0
- data/docs/Tasker/Functions/FunctionBasedDependencyLevels.html +598 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestSteps/SlowestStep.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestSteps.html +453 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestTasks/SlowestTask.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedSlowestTasks.html +453 -0
- data/docs/Tasker/Functions/FunctionBasedStepReadinessStatus.html +1457 -0
- data/docs/Tasker/Functions/FunctionBasedSystemHealthCounts/HealthMetrics.html +135 -0
- data/docs/Tasker/Functions/FunctionBasedSystemHealthCounts.html +370 -0
- data/docs/Tasker/Functions/FunctionBasedTaskExecutionContext.html +1250 -0
- data/docs/Tasker/Functions/FunctionWrapper.html +479 -0
- data/docs/Tasker/Functions.html +117 -0
- data/docs/Tasker/Generators/AuthenticatorGenerator/UsageInstructionsFormatter.html +244 -0
- data/docs/Tasker/Generators/AuthenticatorGenerator.html +373 -0
- data/docs/Tasker/Generators/AuthorizationCoordinatorGenerator.html +430 -0
- data/docs/Tasker/Generators/SubscriberGenerator.html +377 -0
- data/docs/Tasker/Generators/TaskHandlerGenerator.html +263 -0
- data/docs/Tasker/Generators.html +117 -0
- data/docs/Tasker/GraphQLTypes/AnnotationType.html +132 -0
- data/docs/Tasker/GraphQLTypes/BaseArgument.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseConnection.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseEdge.html +130 -0
- data/docs/Tasker/GraphQLTypes/BaseEnum.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseField.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseInputObject.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseInterface.html +116 -0
- data/docs/Tasker/GraphQLTypes/BaseObject.html +128 -0
- data/docs/Tasker/GraphQLTypes/BaseScalar.html +124 -0
- data/docs/Tasker/GraphQLTypes/BaseUnion.html +124 -0
- data/docs/Tasker/GraphQLTypes/DependentSystemObjectMapType.html +132 -0
- data/docs/Tasker/GraphQLTypes/DependentSystemType.html +132 -0
- data/docs/Tasker/GraphQLTypes/MutationType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NamedStepType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NamedTaskType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NamedTasksNamedStepType.html +132 -0
- data/docs/Tasker/GraphQLTypes/NodeType.html +118 -0
- data/docs/Tasker/GraphQLTypes/QueryType.html +139 -0
- data/docs/Tasker/GraphQLTypes/TaskAnnotationType.html +132 -0
- data/docs/Tasker/GraphQLTypes/TaskInterface.html +111 -0
- data/docs/Tasker/GraphQLTypes/TaskType.html +201 -0
- data/docs/Tasker/GraphQLTypes/WorkflowStepType.html +694 -0
- data/docs/Tasker/GraphQLTypes.html +130 -0
- data/docs/Tasker/GraphqlController.html +251 -0
- data/docs/Tasker/HandlerFactory.html +1518 -0
- data/docs/Tasker/HandlerSerializer.html +682 -0
- data/docs/Tasker/HandlersController.html +574 -0
- data/docs/Tasker/HashIdentityStrategy.html +278 -0
- data/docs/Tasker/Health/ReadinessChecker.html +712 -0
- data/docs/Tasker/Health/StatusChecker.html +653 -0
- data/docs/Tasker/Health.html +117 -0
- data/docs/Tasker/HealthController.html +523 -0
- data/docs/Tasker/IdentityStrategy.html +276 -0
- data/docs/Tasker/InvalidTaskHandlerConfig.html +135 -0
- data/docs/Tasker/LifecycleEvents/Events/Step.html +162 -0
- data/docs/Tasker/LifecycleEvents/Events/Task.html +162 -0
- data/docs/Tasker/LifecycleEvents/Events.html +204 -0
- data/docs/Tasker/LifecycleEvents/Publisher.html +132 -0
- data/docs/Tasker/LifecycleEvents.html +799 -0
- data/docs/Tasker/Logging/CorrelationIdGenerator.html +688 -0
- data/docs/Tasker/Logging.html +115 -0
- data/docs/Tasker/MetricsController.html +293 -0
- data/docs/Tasker/MetricsExportJob.html +414 -0
- data/docs/Tasker/Mutations/BaseMutation.html +128 -0
- data/docs/Tasker/Mutations/CancelStep.html +219 -0
- data/docs/Tasker/Mutations/CancelTask.html +221 -0
- data/docs/Tasker/Mutations/CreateTask.html +243 -0
- data/docs/Tasker/Mutations/UpdateStep.html +243 -0
- data/docs/Tasker/Mutations/UpdateTask.html +243 -0
- data/docs/Tasker/Mutations.html +117 -0
- data/docs/Tasker/NamedStep.html +216 -0
- data/docs/Tasker/NamedTask.html +910 -0
- data/docs/Tasker/NamedTasksNamedStep.html +435 -0
- data/docs/Tasker/Orchestration/BackoffCalculator.html +404 -0
- data/docs/Tasker/Orchestration/ConnectionBuilder/ConfigValidator.html +258 -0
- data/docs/Tasker/Orchestration/ConnectionBuilder.html +435 -0
- data/docs/Tasker/Orchestration/ConnectionPoolIntelligence.html +513 -0
- data/docs/Tasker/Orchestration/Coordinator.html +641 -0
- data/docs/Tasker/Orchestration/FutureStateAnalyzer.html +1045 -0
- data/docs/Tasker/Orchestration/Orchestrator.html +679 -0
- data/docs/Tasker/Orchestration/PluginIntegration.html +1127 -0
- data/docs/Tasker/Orchestration/ResponseProcessor.html +504 -0
- data/docs/Tasker/Orchestration/RetryHeaderParser.html +304 -0
- data/docs/Tasker/Orchestration/StepExecutor.html +995 -0
- data/docs/Tasker/Orchestration/StepSequenceFactory.html +644 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/BlockageChecker.html +264 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/ContextManager.html +254 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/DelayCalculator.html +556 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/FinalizationDecisionMaker.html +348 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/FinalizationProcessor.html +286 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/ReasonDeterminer.html +432 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/ReenqueueManager.html +296 -0
- data/docs/Tasker/Orchestration/TaskFinalizer/UnclearStateHandler.html +314 -0
- data/docs/Tasker/Orchestration/TaskFinalizer.html +1212 -0
- data/docs/Tasker/Orchestration/TaskInitializer.html +766 -0
- data/docs/Tasker/Orchestration/TaskReenqueuer.html +506 -0
- data/docs/Tasker/Orchestration/ViableStepDiscovery.html +442 -0
- data/docs/Tasker/Orchestration/WorkflowCoordinator.html +510 -0
- data/docs/Tasker/Orchestration.html +130 -0
- data/docs/Tasker/PageSort/PageSortParamsBuilder.html +296 -0
- data/docs/Tasker/PageSort.html +247 -0
- data/docs/Tasker/PermanentError.html +518 -0
- data/docs/Tasker/ProceduralError.html +147 -0
- data/docs/Tasker/Queries/AllAnnotationTypes.html +217 -0
- data/docs/Tasker/Queries/AllTasks.html +221 -0
- data/docs/Tasker/Queries/BaseQuery.html +128 -0
- data/docs/Tasker/Queries/Helpers.html +187 -0
- data/docs/Tasker/Queries/OneStep.html +225 -0
- data/docs/Tasker/Queries/OneTask.html +217 -0
- data/docs/Tasker/Queries/TasksByAnnotation.html +231 -0
- data/docs/Tasker/Queries/TasksByStatus.html +233 -0
- data/docs/Tasker/Queries.html +119 -0
- data/docs/Tasker/Railtie.html +124 -0
- data/docs/Tasker/Registry/BaseRegistry.html +1690 -0
- data/docs/Tasker/Registry/EventPublisher.html +667 -0
- data/docs/Tasker/Registry/InterfaceValidator.html +569 -0
- data/docs/Tasker/Registry/RegistrationError.html +132 -0
- data/docs/Tasker/Registry/RegistryError.html +139 -0
- data/docs/Tasker/Registry/StatisticsCollector.html +841 -0
- data/docs/Tasker/Registry/SubscriberRegistry.html +1504 -0
- data/docs/Tasker/Registry/ValidationError.html +132 -0
- data/docs/Tasker/Registry.html +119 -0
- data/docs/Tasker/RetryableError.html +515 -0
- data/docs/Tasker/StateMachine/Compatibility.html +282 -0
- data/docs/Tasker/StateMachine/InvalidStateTransition.html +135 -0
- data/docs/Tasker/StateMachine/StepStateMachine/StandardizedPayloadBuilder.html +260 -0
- data/docs/Tasker/StateMachine/StepStateMachine.html +2215 -0
- data/docs/Tasker/StateMachine/TaskStateMachine.html +734 -0
- data/docs/Tasker/StateMachine.html +602 -0
- data/docs/Tasker/StepDagRelationship.html +657 -0
- data/docs/Tasker/StepHandler/Api/Config.html +1091 -0
- data/docs/Tasker/StepHandler/Api.html +884 -0
- data/docs/Tasker/StepHandler/AutomaticEventPublishing.html +321 -0
- data/docs/Tasker/StepHandler/Base.html +970 -0
- data/docs/Tasker/StepHandler.html +119 -0
- data/docs/Tasker/StepReadinessStatus.html +836 -0
- data/docs/Tasker/Task.html +2575 -0
- data/docs/Tasker/TaskAnnotation.html +137 -0
- data/docs/Tasker/TaskAnnotationSerializer.html +124 -0
- data/docs/Tasker/TaskBuilder/StepNameValidator.html +264 -0
- data/docs/Tasker/TaskBuilder/StepTemplateDefiner.html +264 -0
- data/docs/Tasker/TaskBuilder.html +764 -0
- data/docs/Tasker/TaskDiagram/StepToStepEdgeBuilder.html +260 -0
- data/docs/Tasker/TaskDiagram/TaskToRootStepEdgeBuilder.html +290 -0
- data/docs/Tasker/TaskDiagram.html +548 -0
- data/docs/Tasker/TaskDiagramsController.html +240 -0
- data/docs/Tasker/TaskExecutionContext.html +469 -0
- data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner/ClassBasedEventRegistrar.html +238 -0
- data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner/YamlEventRegistrar.html +254 -0
- data/docs/Tasker/TaskHandler/ClassMethods/StepTemplateDefiner.html +988 -0
- data/docs/Tasker/TaskHandler/ClassMethods.html +357 -0
- data/docs/Tasker/TaskHandler/InstanceMethods.html +1396 -0
- data/docs/Tasker/TaskHandler/StepGroup.html +1748 -0
- data/docs/Tasker/TaskHandler.html +271 -0
- data/docs/Tasker/TaskNamespace.html +312 -0
- data/docs/Tasker/TaskRunnerJob.html +406 -0
- data/docs/Tasker/TaskSerializer.html +474 -0
- data/docs/Tasker/TaskTransition.html +1517 -0
- data/docs/Tasker/TaskWorkflowSummary.html +988 -0
- data/docs/Tasker/TaskerRailsSchema/InvalidObjectTypeError.html +132 -0
- data/docs/Tasker/TaskerRailsSchema/TypeResolutionError.html +139 -0
- data/docs/Tasker/TaskerRailsSchema/UnknownInterfaceError.html +132 -0
- data/docs/Tasker/TaskerRailsSchema.html +384 -0
- data/docs/Tasker/TasksController.html +595 -0
- data/docs/Tasker/Telemetry/EventMapping.html +1307 -0
- data/docs/Tasker/Telemetry/EventRouter.html +2178 -0
- data/docs/Tasker/Telemetry/Events/ExportEvents.html +246 -0
- data/docs/Tasker/Telemetry/Events.html +115 -0
- data/docs/Tasker/Telemetry/ExportCoordinator/DistributedLockTimeoutError.html +135 -0
- data/docs/Tasker/Telemetry/ExportCoordinator.html +2137 -0
- data/docs/Tasker/Telemetry/IntelligentCacheManager.html +1083 -0
- data/docs/Tasker/Telemetry/LogBackend.html +1088 -0
- data/docs/Tasker/Telemetry/MetricTypes/Counter.html +1054 -0
- data/docs/Tasker/Telemetry/MetricTypes/Gauge.html +1270 -0
- data/docs/Tasker/Telemetry/MetricTypes/Histogram.html +1492 -0
- data/docs/Tasker/Telemetry/MetricTypes.html +153 -0
- data/docs/Tasker/Telemetry/MetricsBackend.html +2510 -0
- data/docs/Tasker/Telemetry/MetricsExportService.html +578 -0
- data/docs/Tasker/Telemetry/PluginRegistry.html +1774 -0
- data/docs/Tasker/Telemetry/Plugins/BaseExporter.html +1835 -0
- data/docs/Tasker/Telemetry/Plugins/CsvExporter.html +768 -0
- data/docs/Tasker/Telemetry/Plugins/JsonExporter.html +747 -0
- data/docs/Tasker/Telemetry/Plugins.html +117 -0
- data/docs/Tasker/Telemetry/PrometheusExporter.html +481 -0
- data/docs/Tasker/Telemetry/TraceBackend.html +891 -0
- data/docs/Tasker/Telemetry.html +130 -0
- data/docs/Tasker/Types/AuthConfig.html +886 -0
- data/docs/Tasker/Types/BackoffConfig.html +1063 -0
- data/docs/Tasker/Types/BaseConfig.html +227 -0
- data/docs/Tasker/Types/CacheConfig.html +1731 -0
- data/docs/Tasker/Types/DatabaseConfig.html +388 -0
- data/docs/Tasker/Types/DependencyGraph.html +526 -0
- data/docs/Tasker/Types/DependencyGraphConfig.html +753 -0
- data/docs/Tasker/Types/EngineConfig.html +1181 -0
- data/docs/Tasker/Types/ExecutionConfig.html +1963 -0
- data/docs/Tasker/Types/GraphEdge.html +517 -0
- data/docs/Tasker/Types/GraphMetadata.html +781 -0
- data/docs/Tasker/Types/GraphNode.html +694 -0
- data/docs/Tasker/Types/HealthConfig.html +784 -0
- data/docs/Tasker/Types/StepSequence.html +353 -0
- data/docs/Tasker/Types/StepTemplate.html +1193 -0
- data/docs/Tasker/Types/TaskRequest.html +1179 -0
- data/docs/Tasker/Types/TelemetryConfig.html +2746 -0
- data/docs/Tasker/Types.html +154 -0
- data/docs/Tasker/WorkflowStep/StepFinder.html +282 -0
- data/docs/Tasker/WorkflowStep.html +2724 -0
- data/docs/Tasker/WorkflowStepEdge.html +304 -0
- data/docs/Tasker/WorkflowStepSerializer.html +305 -0
- data/docs/Tasker/WorkflowStepTransition/TransitionDescriptionFormatter.html +282 -0
- data/docs/Tasker/WorkflowStepTransition.html +2201 -0
- data/docs/Tasker/WorkflowStepsController.html +462 -0
- data/docs/Tasker.html +452 -0
- data/docs/VISION.md +584 -0
- data/docs/WHY.md +21 -0
- data/docs/_index.html +2375 -0
- data/docs/class_list.html +54 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +503 -0
- data/docs/events/migration_plan_outcomes.md +80 -0
- data/docs/file.README.html +541 -0
- data/docs/file_list.html +59 -0
- data/docs/frames.html +22 -0
- data/docs/index.html +541 -0
- data/docs/js/app.js +344 -0
- data/docs/js/full_list.js +242 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +9182 -0
- data/docs/top-level-namespace.html +110 -0
- data/lib/generators/tasker/authenticator_generator.rb +301 -0
- data/lib/generators/tasker/authorization_coordinator_generator.rb +139 -0
- data/lib/generators/tasker/events_generator.rb +91 -0
- data/lib/generators/tasker/subscriber_generator.rb +107 -0
- data/lib/generators/tasker/task_handler_generator.rb +138 -0
- data/lib/generators/tasker/templates/api_token_authenticator.rb.erb +113 -0
- data/lib/generators/tasker/templates/api_token_authenticator_spec.rb.erb +144 -0
- data/lib/generators/tasker/templates/authorization_coordinator.rb.erb +95 -0
- data/lib/generators/tasker/templates/authorization_coordinator_spec.rb.erb +142 -0
- data/lib/generators/tasker/templates/custom_authenticator.rb.erb +108 -0
- data/lib/generators/tasker/templates/custom_authenticator_spec.rb.erb +162 -0
- data/lib/generators/tasker/templates/custom_events.yml.erb +62 -0
- data/lib/generators/tasker/templates/custom_subscriber.rb.erb +72 -0
- data/lib/generators/tasker/templates/devise_authenticator.rb.erb +101 -0
- data/lib/generators/tasker/templates/devise_authenticator_spec.rb.erb +126 -0
- data/lib/generators/tasker/templates/initialize.rb.erb +202 -0
- data/lib/generators/tasker/templates/jwt_authenticator.rb.erb +144 -0
- data/lib/generators/tasker/templates/jwt_authenticator_spec.rb.erb +298 -0
- data/lib/generators/tasker/templates/metrics_subscriber.rb.erb +258 -0
- data/lib/generators/tasker/templates/metrics_subscriber_spec.rb.erb +308 -0
- data/lib/generators/tasker/templates/omniauth_authenticator.rb.erb +135 -0
- data/lib/generators/tasker/templates/omniauth_authenticator_spec.rb.erb +196 -0
- data/lib/generators/tasker/templates/opentelemetry_initializer.rb +52 -0
- data/lib/generators/tasker/templates/subscriber.rb.erb +64 -0
- data/lib/generators/tasker/templates/subscriber_spec.rb.erb +80 -0
- data/lib/generators/tasker/templates/task_config.yaml.erb +117 -0
- data/lib/generators/tasker/templates/task_handler.rb.erb +59 -0
- data/lib/generators/tasker/templates/task_handler_spec.rb.erb +159 -0
- data/lib/tasker/analysis/runtime_graph_analyzer.rb +1168 -0
- data/lib/tasker/analysis/template_graph_analyzer.rb +328 -0
- data/lib/tasker/authentication/coordinator.rb +78 -0
- data/lib/tasker/authentication/errors.rb +9 -0
- data/lib/tasker/authentication/interface.rb +36 -0
- data/lib/tasker/authentication/none_authenticator.rb +26 -0
- data/lib/tasker/authorization/base_coordinator.rb +112 -0
- data/lib/tasker/authorization/errors.rb +26 -0
- data/lib/tasker/authorization/resource_constants.rb +74 -0
- data/lib/tasker/authorization/resource_registry.rb +143 -0
- data/lib/tasker/authorization.rb +75 -0
- data/lib/tasker/cache_capabilities.rb +131 -0
- data/lib/tasker/cache_strategy.rb +469 -0
- data/lib/tasker/concerns/authenticatable.rb +41 -0
- data/lib/tasker/concerns/authorizable.rb +204 -0
- data/lib/tasker/concerns/controller_authorizable.rb +124 -0
- data/lib/tasker/concerns/event_publisher.rb +716 -0
- data/lib/tasker/concerns/idempotent_state_transitions.rb +128 -0
- data/lib/tasker/concerns/state_machine_base.rb +218 -0
- data/lib/tasker/concerns/structured_logging.rb +387 -0
- data/lib/tasker/configuration.rb +325 -0
- data/lib/tasker/constants/event_definitions.rb +147 -0
- data/lib/tasker/constants/registry_events.rb +54 -0
- data/lib/tasker/constants.rb +417 -0
- data/lib/tasker/engine.rb +90 -0
- data/lib/tasker/errors.rb +90 -0
- data/lib/tasker/events/catalog.rb +432 -0
- data/lib/tasker/events/custom_registry.rb +175 -0
- data/lib/tasker/events/definition_loader.rb +199 -0
- data/lib/tasker/events/event_payload_builder.rb +461 -0
- data/lib/tasker/events/publisher.rb +149 -0
- data/lib/tasker/events/subscribers/base_subscriber.rb +601 -0
- data/lib/tasker/events/subscribers/metrics_subscriber.rb +120 -0
- data/lib/tasker/events/subscribers/telemetry_subscriber.rb +462 -0
- data/lib/tasker/events/subscription_loader.rb +161 -0
- data/lib/tasker/events.rb +37 -0
- data/lib/tasker/functions/function_based_analytics_metrics.rb +103 -0
- data/lib/tasker/functions/function_based_dependency_levels.rb +54 -0
- data/lib/tasker/functions/function_based_slowest_steps.rb +84 -0
- data/lib/tasker/functions/function_based_slowest_tasks.rb +84 -0
- data/lib/tasker/functions/function_based_step_readiness_status.rb +183 -0
- data/lib/tasker/functions/function_based_system_health_counts.rb +94 -0
- data/lib/tasker/functions/function_based_task_execution_context.rb +148 -0
- data/lib/tasker/functions/function_wrapper.rb +42 -0
- data/lib/tasker/functions.rb +12 -0
- data/lib/tasker/handler_factory.rb +322 -0
- data/lib/tasker/health/readiness_checker.rb +186 -0
- data/lib/tasker/health/status_checker.rb +203 -0
- data/lib/tasker/identity_strategy.rb +38 -0
- data/lib/tasker/logging/correlation_id_generator.rb +120 -0
- data/lib/tasker/orchestration/backoff_calculator.rb +184 -0
- data/lib/tasker/orchestration/connection_builder.rb +122 -0
- data/lib/tasker/orchestration/connection_pool_intelligence.rb +177 -0
- data/lib/tasker/orchestration/coordinator.rb +119 -0
- data/lib/tasker/orchestration/future_state_analyzer.rb +137 -0
- data/lib/tasker/orchestration/plugin_integration.rb +124 -0
- data/lib/tasker/orchestration/response_processor.rb +168 -0
- data/lib/tasker/orchestration/retry_header_parser.rb +78 -0
- data/lib/tasker/orchestration/step_executor.rb +941 -0
- data/lib/tasker/orchestration/step_sequence_factory.rb +67 -0
- data/lib/tasker/orchestration/task_finalizer.rb +564 -0
- data/lib/tasker/orchestration/task_initializer.rb +140 -0
- data/lib/tasker/orchestration/task_reenqueuer.rb +71 -0
- data/lib/tasker/orchestration/viable_step_discovery.rb +65 -0
- data/lib/tasker/orchestration/workflow_coordinator.rb +294 -0
- data/lib/tasker/orchestration.rb +45 -0
- data/lib/tasker/railtie.rb +9 -0
- data/lib/tasker/registry/base_registry.rb +177 -0
- data/lib/tasker/registry/event_publisher.rb +91 -0
- data/lib/tasker/registry/interface_validator.rb +140 -0
- data/lib/tasker/registry/statistics_collector.rb +381 -0
- data/lib/tasker/registry/subscriber_registry.rb +285 -0
- data/lib/tasker/registry.rb +22 -0
- data/lib/tasker/state_machine/step_state_machine.rb +508 -0
- data/lib/tasker/state_machine/task_state_machine.rb +192 -0
- data/lib/tasker/state_machine.rb +83 -0
- data/lib/tasker/step_handler/api.rb +410 -0
- data/lib/tasker/step_handler/base.rb +206 -0
- data/lib/tasker/task_builder.rb +432 -0
- data/lib/tasker/task_handler/class_methods.rb +324 -0
- data/lib/tasker/task_handler/instance_methods.rb +293 -0
- data/lib/tasker/task_handler/step_group.rb +182 -0
- data/lib/tasker/task_handler.rb +43 -0
- data/lib/tasker/telemetry/event_mapping.rb +126 -0
- data/lib/tasker/telemetry/event_router.rb +318 -0
- data/lib/tasker/telemetry/events/export_events.rb +38 -0
- data/lib/tasker/telemetry/export_coordinator.rb +497 -0
- data/lib/tasker/telemetry/intelligent_cache_manager.rb +508 -0
- data/lib/tasker/telemetry/log_backend.rb +224 -0
- data/lib/tasker/telemetry/metric_types.rb +368 -0
- data/lib/tasker/telemetry/metrics_backend.rb +1227 -0
- data/lib/tasker/telemetry/metrics_export_service.rb +392 -0
- data/lib/tasker/telemetry/plugin_registry.rb +333 -0
- data/lib/tasker/telemetry/plugins/base_exporter.rb +246 -0
- data/lib/tasker/telemetry/plugins/csv_exporter.rb +198 -0
- data/lib/tasker/telemetry/plugins/json_exporter.rb +141 -0
- data/lib/tasker/telemetry/prometheus_exporter.rb +249 -0
- data/lib/tasker/telemetry/trace_backend.rb +186 -0
- data/lib/tasker/telemetry.rb +59 -0
- data/lib/tasker/types/auth_config.rb +81 -0
- data/lib/tasker/types/backoff_config.rb +142 -0
- data/lib/tasker/types/cache_config.rb +257 -0
- data/lib/tasker/types/database_config.rb +39 -0
- data/lib/tasker/types/dependency_graph.rb +225 -0
- data/lib/tasker/types/dependency_graph_config.rb +149 -0
- data/lib/tasker/types/engine_config.rb +131 -0
- data/lib/tasker/types/execution_config.rb +289 -0
- data/lib/tasker/types/health_config.rb +84 -0
- data/lib/tasker/types/step_sequence.rb +24 -0
- data/lib/tasker/types/step_template.rb +63 -0
- data/lib/tasker/types/task_request.rb +60 -0
- data/lib/tasker/types/telemetry_config.rb +273 -0
- data/lib/tasker/types.rb +64 -0
- data/lib/tasker/version.rb +7 -0
- data/lib/tasker.rb +82 -0
- data/lib/tasks/tasker_tasks.rake +302 -0
- metadata +958 -0
data/docs/VISION.md
ADDED
@@ -0,0 +1,584 @@
|
|
1
|
+
# Tasker Strategic Roadmap: Distributed AI-Integrated Workflow Orchestration
|
2
|
+
|
3
|
+
## Vision Statement
|
4
|
+
|
5
|
+
**Transform Tasker from a Rails-native workflow engine into a distributed, AI-integrated orchestration platform that enables polyglot systems to coordinate complex workflows while maintaining the reliability, observability, and predictability that makes Tasker production-ready.**
|
6
|
+
|
7
|
+
## Core Architectural Evolution
|
8
|
+
|
9
|
+
### Current Foundation (Tasker 2.4.0)
|
10
|
+
- ✅ **Single-system orchestration** with Rails-native patterns
|
11
|
+
- ✅ **High-performance SQL functions** for step readiness calculation
|
12
|
+
- ✅ **Thread-safe registry systems** with structured logging
|
13
|
+
- ✅ **Comprehensive event system** with OpenTelemetry integration
|
14
|
+
- ✅ **Production-proven reliability** with exponential backoff and retry logic
|
15
|
+
|
16
|
+
### Target Architecture Vision
|
17
|
+
- 🎯 **Distributed workflow coordination** across polyglot systems
|
18
|
+
- 🎯 **Rust-based performance core** with language bindings
|
19
|
+
- 🎯 **AI-integrated workflow design** and failure resolution
|
20
|
+
- 🎯 **Structured result contracts** with type safety
|
21
|
+
- 🎯 **Service bus event architecture** for cross-system coordination
|
22
|
+
|
23
|
+
---
|
24
|
+
|
25
|
+
## Phase 1: Foundation Strengthening (6-9 months)
|
26
|
+
*"Making Tasker ready for distributed architecture"*
|
27
|
+
|
28
|
+
### 1.1 Structured Result Contracts
|
29
|
+
**Problem**: Free-form `step.results` creates integration brittleness in distributed systems.
|
30
|
+
|
31
|
+
**Solution**: Self-describing step result schemas with validation.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
# Current (2.4.0)
|
35
|
+
def process(task, sequence, step)
|
36
|
+
{ user_id: 123, status: 'created' } # Free-form results
|
37
|
+
end
|
38
|
+
|
39
|
+
# Target Architecture
|
40
|
+
class CreateUserHandler < Tasker::StepHandler::Base
|
41
|
+
result_contract do
|
42
|
+
success_schema do
|
43
|
+
field :user_id, Integer, required: true
|
44
|
+
field :email, String, format: :email
|
45
|
+
field :created_at, DateTime
|
46
|
+
end
|
47
|
+
|
48
|
+
error_schema do
|
49
|
+
field :error_code, String, enum: ['validation_failed', 'duplicate_email']
|
50
|
+
field :error_message, String
|
51
|
+
field :retry_after, Integer, optional: true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def process(task, sequence, step)
|
56
|
+
# Results automatically validated against contract
|
57
|
+
create_user_result
|
58
|
+
end
|
59
|
+
end
|
60
|
+
```
|
61
|
+
|
62
|
+
**Benefits**:
|
63
|
+
- **Type safety** for dependent steps
|
64
|
+
- **Integration testing** can validate contracts
|
65
|
+
- **API documentation** auto-generated from schemas
|
66
|
+
- **Foundation for Rust FFI** type mappings
|
67
|
+
|
68
|
+
### 1.2 Event-Driven Step Architecture
|
69
|
+
**Problem**: Current step execution is tightly coupled to single-system boundaries.
|
70
|
+
|
71
|
+
**Solution**: Event-driven step execution with pluggable handlers.
|
72
|
+
|
73
|
+
```ruby
|
74
|
+
# Local Step Handler (current pattern)
|
75
|
+
class LocalPaymentHandler < Tasker::StepHandler::Base
|
76
|
+
def process(task, sequence, step)
|
77
|
+
PaymentService.charge(task.context['amount'])
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Event-Driven Step Handler (distributed-ready)
|
82
|
+
class DistributedPaymentHandler < Tasker::StepHandler::EventDriven
|
83
|
+
event_target 'payment_service_queue'
|
84
|
+
timeout 30.seconds
|
85
|
+
|
86
|
+
def create_event_payload(task, sequence, step)
|
87
|
+
{
|
88
|
+
event_type: 'payment.charge_requested',
|
89
|
+
order_id: task.context['order_id'],
|
90
|
+
amount: task.context['amount'],
|
91
|
+
reply_to: "tasker.#{task.id}.#{step.id}"
|
92
|
+
}
|
93
|
+
end
|
94
|
+
|
95
|
+
def validate_event_response(response)
|
96
|
+
# Validate against result contract
|
97
|
+
response.has_key?('transaction_id') && response['status'] == 'completed'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
```
|
101
|
+
|
102
|
+
### 1.3 Service Bus Integration Layer
|
103
|
+
**Problem**: No coordination mechanism for cross-system workflows.
|
104
|
+
|
105
|
+
**Solution**: Pluggable service bus abstraction with multiple backend support.
|
106
|
+
|
107
|
+
```ruby
|
108
|
+
# Configuration
|
109
|
+
Tasker.configuration do |config|
|
110
|
+
config.service_bus do |bus|
|
111
|
+
bus.backend = :rabbitmq # or :kafka, :redis, :nats
|
112
|
+
bus.connection_url = ENV['SERVICE_BUS_URL']
|
113
|
+
bus.exchange_prefix = 'tasker.workflows'
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# Usage in step handlers
|
118
|
+
class ServiceBusStepHandler < Tasker::StepHandler::Base
|
119
|
+
include Tasker::ServiceBus::Publisher
|
120
|
+
|
121
|
+
def process(task, sequence, step)
|
122
|
+
publish_event('inventory.check_stock', {
|
123
|
+
product_ids: task.context['products'],
|
124
|
+
reply_to: reply_channel(step)
|
125
|
+
})
|
126
|
+
|
127
|
+
# Return immediately - completion handled by event consumer
|
128
|
+
{ status: 'dispatched', event_id: SecureRandom.uuid }
|
129
|
+
end
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
**Key Features**:
|
134
|
+
- **Backend agnostic** (RabbitMQ, Kafka, Redis, NATS)
|
135
|
+
- **Automatic retry logic** using service bus retry mechanisms
|
136
|
+
- **Dead letter handling** for failed cross-system calls
|
137
|
+
- **Event correlation** for tracking distributed operations
|
138
|
+
|
139
|
+
---
|
140
|
+
|
141
|
+
## Phase 2: Distributed Coordination (9-15 months)
|
142
|
+
*"Enabling true polyglot workflow orchestration"*
|
143
|
+
|
144
|
+
### 2.1 Cross-System Workflow Definition
|
145
|
+
**Problem**: Workflows currently assume single-system ownership of all steps.
|
146
|
+
|
147
|
+
**Solution**: Distributed workflow manifests with system ownership mapping.
|
148
|
+
|
149
|
+
```yaml
|
150
|
+
# config/tasker/distributed_workflows/order_processing.yaml
|
151
|
+
name: distributed_order_processing
|
152
|
+
version: 2.0.0
|
153
|
+
systems:
|
154
|
+
rails_app:
|
155
|
+
base_url: 'https://orders.company.com'
|
156
|
+
capabilities: ['order.validate', 'order.finalize']
|
157
|
+
python_inventory:
|
158
|
+
base_url: 'https://inventory.company.com'
|
159
|
+
capabilities: ['inventory.check', 'inventory.reserve']
|
160
|
+
node_payments:
|
161
|
+
base_url: 'https://payments.company.com'
|
162
|
+
capabilities: ['payment.process', 'payment.refund']
|
163
|
+
|
164
|
+
workflow_steps:
|
165
|
+
- name: validate_order
|
166
|
+
owner: rails_app
|
167
|
+
handler: 'Orders::ValidateOrderHandler'
|
168
|
+
|
169
|
+
- name: check_inventory
|
170
|
+
owner: python_inventory
|
171
|
+
depends_on: validate_order
|
172
|
+
event_pattern: 'inventory.check_stock'
|
173
|
+
timeout: 30s
|
174
|
+
|
175
|
+
- name: process_payment
|
176
|
+
owner: node_payments
|
177
|
+
depends_on: check_inventory
|
178
|
+
event_pattern: 'payment.charge'
|
179
|
+
timeout: 45s
|
180
|
+
|
181
|
+
- name: finalize_order
|
182
|
+
owner: rails_app
|
183
|
+
depends_on: process_payment
|
184
|
+
handler: 'Orders::FinalizeOrderHandler'
|
185
|
+
```
|
186
|
+
|
187
|
+
### 2.2 System Registry & Discovery
|
188
|
+
**Problem**: No mechanism for systems to discover each other's capabilities.
|
189
|
+
|
190
|
+
**Solution**: Distributed system registry with capability advertisement.
|
191
|
+
|
192
|
+
```ruby
|
193
|
+
# System registration
|
194
|
+
Tasker::DistributedRegistry.register_system(
|
195
|
+
name: 'python_inventory',
|
196
|
+
version: '1.2.0',
|
197
|
+
capabilities: [
|
198
|
+
{
|
199
|
+
name: 'inventory.check_stock',
|
200
|
+
input_schema: InventoryCheckSchema,
|
201
|
+
output_schema: InventoryResultSchema,
|
202
|
+
timeout: 30.seconds
|
203
|
+
}
|
204
|
+
],
|
205
|
+
health_check_url: 'https://inventory.company.com/health'
|
206
|
+
)
|
207
|
+
|
208
|
+
# Workflow coordinator uses registry for routing
|
209
|
+
coordinator = Tasker::DistributedCoordinator.new
|
210
|
+
coordinator.route_step('check_inventory', to: 'python_inventory')
|
211
|
+
```
|
212
|
+
|
213
|
+
### 2.3 Rust Core Foundation
|
214
|
+
**Problem**: Performance bottlenecks and memory safety concerns for high-scale distributed coordination.
|
215
|
+
|
216
|
+
**Solution**: Extract core orchestration logic to Rust with FFI bindings.
|
217
|
+
|
218
|
+
```rust
|
219
|
+
// Core Rust types
|
220
|
+
#[derive(Debug, Serialize, Deserialize)]
|
221
|
+
pub struct WorkflowStep {
|
222
|
+
pub id: i64,
|
223
|
+
pub name: String,
|
224
|
+
pub status: StepStatus,
|
225
|
+
pub owner_system: String,
|
226
|
+
pub dependencies: Vec<i64>,
|
227
|
+
pub result_contract: Option<ResultContract>,
|
228
|
+
}
|
229
|
+
|
230
|
+
// High-performance dependency resolution
|
231
|
+
pub fn calculate_ready_steps(
|
232
|
+
workflow: &Workflow,
|
233
|
+
completed_steps: &[i64]
|
234
|
+
) -> Vec<WorkflowStep> {
|
235
|
+
// Zero-allocation dependency graph traversal
|
236
|
+
}
|
237
|
+
|
238
|
+
// Ruby FFI binding
|
239
|
+
impl WorkflowEngine {
|
240
|
+
#[magnus::method]
|
241
|
+
pub fn get_ready_steps(&self, workflow_id: i64) -> Vec<StepData> {
|
242
|
+
// Bridge between Rust and Ruby types
|
243
|
+
}
|
244
|
+
}
|
245
|
+
```
|
246
|
+
|
247
|
+
**Performance Targets**:
|
248
|
+
- **Dependency calculation**: <100μs for 1000+ step workflows
|
249
|
+
- **Memory usage**: <1MB per 10,000 active workflows
|
250
|
+
- **Cross-system coordination**: <10ms overhead per distributed step
|
251
|
+
|
252
|
+
---
|
253
|
+
|
254
|
+
## Phase 3: AI Integration Foundation (12-18 months)
|
255
|
+
*"Making workflows intelligent and adaptive"*
|
256
|
+
|
257
|
+
### 3.1 AI-Assisted Failure Resolution
|
258
|
+
**Problem**: Static retry logic cannot adapt to novel failure scenarios.
|
259
|
+
|
260
|
+
**Solution**: AI agents that can diagnose failures and suggest resolutions.
|
261
|
+
|
262
|
+
```ruby
|
263
|
+
class AIAssistedStepHandler < Tasker::StepHandler::Base
|
264
|
+
include Tasker::AI::FailureAnalysis
|
265
|
+
|
266
|
+
def process(task, sequence, step)
|
267
|
+
payment_result = PaymentService.charge(task.context['amount'])
|
268
|
+
rescue PaymentGatewayError => e
|
269
|
+
# AI analysis of failure context
|
270
|
+
diagnosis = analyze_failure(
|
271
|
+
error: e,
|
272
|
+
step_context: step.context,
|
273
|
+
historical_failures: similar_failures(e.class, 1.week)
|
274
|
+
)
|
275
|
+
|
276
|
+
if diagnosis.has_workaround?
|
277
|
+
# Present options to user/operator
|
278
|
+
present_resolution_options(diagnosis)
|
279
|
+
mark_step_pending_manual_resolution(step, diagnosis)
|
280
|
+
else
|
281
|
+
# Standard retry logic
|
282
|
+
raise e
|
283
|
+
end
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
# AI Diagnosis Response
|
288
|
+
{
|
289
|
+
failure_type: 'payment_gateway_timeout',
|
290
|
+
confidence: 0.87,
|
291
|
+
suggested_workarounds: [
|
292
|
+
{
|
293
|
+
type: 'retry_with_different_gateway',
|
294
|
+
confidence: 0.72,
|
295
|
+
implementation: 'Switch to backup payment processor'
|
296
|
+
},
|
297
|
+
{
|
298
|
+
type: 'manual_payment_processing',
|
299
|
+
confidence: 0.95,
|
300
|
+
implementation: 'Process payment manually and mark resolved'
|
301
|
+
}
|
302
|
+
],
|
303
|
+
historical_context: '23 similar failures in past week, 89% resolved with gateway switch'
|
304
|
+
}
|
305
|
+
```
|
306
|
+
|
307
|
+
### 3.2 Natural Language Workflow Generation
|
308
|
+
**Problem**: Creating workflows requires deep technical knowledge of Tasker patterns.
|
309
|
+
|
310
|
+
**Solution**: AI agents that generate workflow configurations from natural language descriptions.
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
# Natural language input
|
314
|
+
user_description = """
|
315
|
+
I need a workflow that:
|
316
|
+
1. Validates a new user registration with email verification
|
317
|
+
2. Creates their profile in our user service
|
318
|
+
3. Sets up their billing account in Stripe
|
319
|
+
4. Sends them a welcome email with onboarding steps
|
320
|
+
5. If anything fails, notify our support team
|
321
|
+
|
322
|
+
The user service is a Python FastAPI app, billing is handled by our Node.js payments service.
|
323
|
+
"""
|
324
|
+
|
325
|
+
# AI-generated workflow
|
326
|
+
workflow_generator = Tasker::AI::WorkflowGenerator.new
|
327
|
+
generated_config = workflow_generator.generate_from_description(
|
328
|
+
description: user_description,
|
329
|
+
available_systems: ['rails_main', 'python_users', 'node_payments'],
|
330
|
+
user_context: current_user
|
331
|
+
)
|
332
|
+
|
333
|
+
# Output: Complete YAML configuration + Ruby step handlers
|
334
|
+
# - Proper dependency chains
|
335
|
+
# - Error handling patterns
|
336
|
+
# - System ownership mapping
|
337
|
+
# - Result contract definitions
|
338
|
+
```
|
339
|
+
|
340
|
+
### 3.3 Intelligent Workflow Optimization
|
341
|
+
**Problem**: Workflows may have non-optimal execution patterns or bottlenecks.
|
342
|
+
|
343
|
+
**Solution**: AI analysis of workflow execution patterns with optimization suggestions.
|
344
|
+
|
345
|
+
```ruby
|
346
|
+
# Continuous workflow analysis
|
347
|
+
class WorkflowIntelligence
|
348
|
+
def analyze_workflow_performance(workflow_name, time_window: 30.days)
|
349
|
+
executions = WorkflowExecution.where(name: workflow_name)
|
350
|
+
.where('created_at > ?', time_window.ago)
|
351
|
+
|
352
|
+
analysis = {
|
353
|
+
bottlenecks: identify_bottleneck_steps(executions),
|
354
|
+
parallel_opportunities: find_parallelization_options(executions),
|
355
|
+
retry_patterns: analyze_retry_effectiveness(executions),
|
356
|
+
suggested_optimizations: generate_optimization_suggestions(executions)
|
357
|
+
}
|
358
|
+
|
359
|
+
# AI-generated recommendations
|
360
|
+
{
|
361
|
+
critical_path_optimization: "Steps 'validate_user' and 'check_email' can run in parallel",
|
362
|
+
retry_tuning: "Step 'external_api_call' succeeds 94% on 2nd retry, consider reducing retry_limit to 2",
|
363
|
+
timeout_adjustment: "Step 'slow_calculation' averages 45s, increase timeout from 30s to 60s",
|
364
|
+
dependency_optimization: "Remove unnecessary dependency between 'send_email' and 'update_analytics'"
|
365
|
+
}
|
366
|
+
end
|
367
|
+
end
|
368
|
+
```
|
369
|
+
|
370
|
+
---
|
371
|
+
|
372
|
+
## Phase 4: Advanced AI Integration (18-24 months)
|
373
|
+
*"Autonomous workflow management and creation"*
|
374
|
+
|
375
|
+
### 4.1 No-Code Workflow Builder with AI
|
376
|
+
**Problem**: Non-technical users cannot create or modify workflows.
|
377
|
+
|
378
|
+
**Solution**: Visual workflow builder with AI-powered step generation.
|
379
|
+
|
380
|
+
```ruby
|
381
|
+
# AI-powered step suggestions
|
382
|
+
class AIWorkflowBuilder
|
383
|
+
def suggest_next_steps(current_workflow, business_context)
|
384
|
+
# Analyze partial workflow and suggest completions
|
385
|
+
suggestions = ai_model.complete_workflow(
|
386
|
+
partial_workflow: current_workflow,
|
387
|
+
business_domain: business_context[:domain],
|
388
|
+
available_integrations: system_registry.available_capabilities,
|
389
|
+
user_patterns: user_workflow_history
|
390
|
+
)
|
391
|
+
|
392
|
+
# Return composable, pre-built step templates
|
393
|
+
suggestions.map do |suggestion|
|
394
|
+
{
|
395
|
+
step_name: suggestion[:name],
|
396
|
+
description: suggestion[:description],
|
397
|
+
handler_template: generate_handler_code(suggestion),
|
398
|
+
estimated_execution_time: suggestion[:timing],
|
399
|
+
dependencies: suggestion[:suggested_dependencies],
|
400
|
+
risk_level: suggestion[:complexity_score]
|
401
|
+
}
|
402
|
+
end
|
403
|
+
end
|
404
|
+
end
|
405
|
+
|
406
|
+
# Visual builder integration
|
407
|
+
class WorkflowCanvas
|
408
|
+
def add_ai_suggested_step(suggestion)
|
409
|
+
# Create step with pre-generated handler
|
410
|
+
# Connect to existing workflow graph
|
411
|
+
# Validate dependencies and contracts
|
412
|
+
# Generate test cases automatically
|
413
|
+
end
|
414
|
+
end
|
415
|
+
```
|
416
|
+
|
417
|
+
### 4.2 MCP Server Integration
|
418
|
+
**Problem**: Limited programmatic access to Tasker insights and management.
|
419
|
+
|
420
|
+
**Solution**: Native MCP servers for workflow intelligence and management.
|
421
|
+
|
422
|
+
```typescript
|
423
|
+
// MCP Server for Tasker Workflow Management
|
424
|
+
export const taskerMCPServer = {
|
425
|
+
name: "tasker-workflow-orchestration",
|
426
|
+
version: "1.0.0",
|
427
|
+
|
428
|
+
tools: [
|
429
|
+
{
|
430
|
+
name: "analyze_workflow_performance",
|
431
|
+
description: "Analyze workflow execution patterns and suggest optimizations",
|
432
|
+
inputSchema: {
|
433
|
+
type: "object",
|
434
|
+
properties: {
|
435
|
+
workflow_name: { type: "string" },
|
436
|
+
time_window: { type: "string", default: "30d" }
|
437
|
+
}
|
438
|
+
}
|
439
|
+
},
|
440
|
+
|
441
|
+
{
|
442
|
+
name: "create_workflow_from_description",
|
443
|
+
description: "Generate a complete workflow from natural language description",
|
444
|
+
inputSchema: {
|
445
|
+
type: "object",
|
446
|
+
properties: {
|
447
|
+
description: { type: "string" },
|
448
|
+
target_systems: { type: "array", items: { type: "string" } }
|
449
|
+
}
|
450
|
+
}
|
451
|
+
},
|
452
|
+
|
453
|
+
{
|
454
|
+
name: "diagnose_workflow_failure",
|
455
|
+
description: "AI-powered diagnosis of workflow failures with resolution suggestions",
|
456
|
+
inputSchema: {
|
457
|
+
type: "object",
|
458
|
+
properties: {
|
459
|
+
task_id: { type: "string" },
|
460
|
+
include_historical_context: { type: "boolean", default: true }
|
461
|
+
}
|
462
|
+
}
|
463
|
+
},
|
464
|
+
|
465
|
+
{
|
466
|
+
name: "optimize_workflow_dependencies",
|
467
|
+
description: "Suggest dependency optimizations for improved parallelization",
|
468
|
+
inputSchema: {
|
469
|
+
type: "object",
|
470
|
+
properties: {
|
471
|
+
workflow_name: { type: "string" }
|
472
|
+
}
|
473
|
+
}
|
474
|
+
}
|
475
|
+
]
|
476
|
+
};
|
477
|
+
|
478
|
+
// Integration with AI assistants
|
479
|
+
async function handleWorkflowAnalysis(request: MCPRequest) {
|
480
|
+
const analysis = await TaskerIntelligence.analyzeWorkflow(request.params);
|
481
|
+
|
482
|
+
return {
|
483
|
+
performance_metrics: analysis.metrics,
|
484
|
+
optimization_suggestions: analysis.suggestions,
|
485
|
+
ai_insights: analysis.ai_recommendations,
|
486
|
+
actionable_improvements: analysis.improvements.map(formatForImplementation)
|
487
|
+
};
|
488
|
+
}
|
489
|
+
```
|
490
|
+
|
491
|
+
### 4.3 Autonomous Workflow Healing
|
492
|
+
**Problem**: Workflows may degrade over time or encounter novel failure modes.
|
493
|
+
|
494
|
+
**Solution**: Self-healing workflows that adapt to changing conditions.
|
495
|
+
|
496
|
+
```ruby
|
497
|
+
class AutonomousWorkflowManager
|
498
|
+
def monitor_and_heal(workflow_name)
|
499
|
+
health_metrics = continuously_monitor_workflow(workflow_name)
|
500
|
+
|
501
|
+
if health_metrics.degraded?
|
502
|
+
healing_actions = generate_healing_strategy(health_metrics)
|
503
|
+
|
504
|
+
healing_actions.each do |action|
|
505
|
+
case action[:type]
|
506
|
+
when :adjust_timeouts
|
507
|
+
auto_adjust_step_timeouts(action[:step_name], action[:new_timeout])
|
508
|
+
|
509
|
+
when :add_circuit_breaker
|
510
|
+
inject_circuit_breaker_pattern(action[:step_name], action[:thresholds])
|
511
|
+
|
512
|
+
when :modify_retry_strategy
|
513
|
+
update_retry_configuration(action[:step_name], action[:strategy])
|
514
|
+
|
515
|
+
when :suggest_architectural_change
|
516
|
+
notify_engineering_team(action[:recommendation])
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
private
|
523
|
+
|
524
|
+
def generate_healing_strategy(health_metrics)
|
525
|
+
# AI-powered analysis of degradation patterns
|
526
|
+
# Historical pattern matching
|
527
|
+
# Predictive failure prevention
|
528
|
+
# Safe autonomous adjustments vs. human-required changes
|
529
|
+
end
|
530
|
+
end
|
531
|
+
```
|
532
|
+
|
533
|
+
---
|
534
|
+
|
535
|
+
## Implementation Strategy & Considerations
|
536
|
+
|
537
|
+
### Technical Architecture Principles
|
538
|
+
|
539
|
+
1. **Backward Compatibility**: Each phase builds on previous work without breaking existing functionality
|
540
|
+
2. **Incremental Adoption**: Features can be adopted gradually without requiring full migration
|
541
|
+
3. **Production Safety**: All AI-assisted features include human oversight and rollback mechanisms
|
542
|
+
4. **Performance First**: Rust core provides foundation for high-scale distributed coordination
|
543
|
+
5. **Type Safety**: Result contracts and schema validation prevent distributed system brittleness
|
544
|
+
|
545
|
+
### Risk Mitigation Strategies
|
546
|
+
|
547
|
+
**AI Integration Risks**:
|
548
|
+
- **Hallucination Protection**: All AI-generated configurations validated against known patterns
|
549
|
+
- **Human Oversight**: Critical decisions require human approval
|
550
|
+
- **Rollback Mechanisms**: Easy reversal of AI-suggested changes
|
551
|
+
- **Confidence Scoring**: AI suggestions include confidence levels and uncertainty bounds
|
552
|
+
|
553
|
+
**Distributed System Risks**:
|
554
|
+
- **Circuit Breakers**: Automatic fallback when remote systems are unavailable
|
555
|
+
- **Timeout Management**: Configurable timeouts with exponential backoff
|
556
|
+
- **Service Discovery**: Health checks and capability validation
|
557
|
+
- **Data Consistency**: Eventually consistent with conflict resolution strategies
|
558
|
+
|
559
|
+
**Performance Risks**:
|
560
|
+
- **Rust Migration**: Incremental extraction with performance benchmarking
|
561
|
+
- **Memory Management**: Bounded queues and resource limits
|
562
|
+
- **Monitoring**: Comprehensive observability for distributed operations
|
563
|
+
- **Graceful Degradation**: System continues operating with reduced functionality
|
564
|
+
|
565
|
+
### Success Metrics
|
566
|
+
|
567
|
+
**Phase 1**: Structured result contracts adopted, event-driven steps working, service bus integration functional
|
568
|
+
**Phase 2**: Multi-system workflows executing successfully, Rust core performance targets met
|
569
|
+
**Phase 3**: AI failure analysis reducing manual intervention by 60%, natural language workflow generation in use
|
570
|
+
**Phase 4**: No-code workflow creation by non-technical users, autonomous healing preventing 80% of degradation issues
|
571
|
+
|
572
|
+
---
|
573
|
+
|
574
|
+
## Long-term Impact Vision
|
575
|
+
|
576
|
+
**For Developers**: Tasker becomes the de facto standard for polyglot workflow orchestration, with AI assistance making complex distributed systems accessible to broader engineering teams.
|
577
|
+
|
578
|
+
**For Operations**: Autonomous healing and AI-powered diagnostics dramatically reduce operational overhead while maintaining the reliability and observability that make Tasker production-ready.
|
579
|
+
|
580
|
+
**For Business**: Natural language workflow creation and no-code builders enable business stakeholders to directly participate in process automation without requiring deep technical expertise.
|
581
|
+
|
582
|
+
**For the Industry**: Tasker establishes new patterns for AI-integrated distributed systems that maintain the rigor and predictability required for business-critical workflows while providing the adaptability needed for novel situations.
|
583
|
+
|
584
|
+
This roadmap preserves Tasker's core strength—reliable, observable, predictable workflow orchestration—while evolving it into an intelligent, distributed platform that can coordinate complex processes across heterogeneous systems with AI-powered assistance and autonomous optimization.
|
data/docs/WHY.md
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Why Tasker?
|
2
|
+
|
3
|
+
That's a good question - Tasker is a pretty specialized kind of abstraction that many organizations may never really need. But as event-driven architectures become the norm, and as even smaller organizations find themselves interacting with a significant number of microservices, SaaS platforms, data stores, event queues, and the like, managing this complexity becomes a problem at scale.
|
4
|
+
|
5
|
+
## Doesn't Sidekiq already exist? (or insert your favorite queuing broker)
|
6
|
+
|
7
|
+
It does! I love [Sidekiq](https://sidekiq.org/) and Tasker is built on top of it. But this solves a little bit of a different problem.
|
8
|
+
|
9
|
+
In event-driven architectures, it is not uncommon for the successful completion of any single "task" to actually be dependent on a significant number of "steps" - and these steps often rely on interacting with a number of different external and internal systems, whether an external API, a local datastore, or an in-house microservice. The success of a given task is therefore dependent on the successful completion of each step, and steps can likewise be dependent on other steps.
|
10
|
+
|
11
|
+
The task itself may be enqueued for processing more than once, while steps are in a backoff or retry state. There are situations where a task and all of it steps may be able to be processed sequentially and successfully completed. In this case, the first time a task is enqueued, it is processed to completion, and will not be enqueued again. However, there are situations where a step's status is still in a valid state, but not complete, waiting on other steps, waiting on remote backoff requests, waiting on retrying from a remote failure, etc. When working with integrated services, APIs, etc that may fail, having retryability and resiliency around *each step* is crucial. If a step fails, it can be retried up to its retry limit, before we consider it in a final-error state. It is only a task which has one or more steps in a final-error (no retries left) that would mark a task as itself in error and no longer re-enquable. Any task that has still-viable steps that cannot be processed immediately, will simply be re-enqueued. The task and its steps retain the state of inputs, outputs, successes, and failures, so that implementing logic for different workflows do not have to repeat this logic over and over.
|
12
|
+
|
13
|
+
## Consider an Example
|
14
|
+
|
15
|
+
Consider a common scenario of receiving an e-commerce order in a multi-channel sales scenario, where fulfillment is managed on-site by an organization. Fulfillment systems have different data stores than the e-commerce solution, of course, but changes to an "order" in the abstract may have mutual effects on both the e-commerce representation of an order and the fulfillment order. When a change should be made to one, very frequently that change should, in some manner, propagate to both. Or, similarly, when an order is shipped, perhaps final taxes need to be calculated and reported to a tax SaaS platform, have the response data stored, and finally in total synced to a data warehouse for financial consistency. The purpose of Tasker is to make it more straightforward to enable event-driven architectures to handle multi-step tasks in a consistent and predictable way, with exposure to visibility in terms of results, status of steps, retryability, timeouts and backoffs, etc.
|
16
|
+
|
17
|
+
## Technology Choices
|
18
|
+
|
19
|
+
I originally developed this as a [standalone application](https://github.com/tasker-systems/tasker_rails), but it felt like this would be a really good opportunity to convert it to a Rails Engine. For my day-to-day professional life I've been working pretty deeply with microservices and domain driven design patterns, but my current role has me back in a Rails monolith - in some ways, it feels good to be home! However, if we were ever going to use something like this in my current role, we would want it to be an Engine so it could be built and maintained external to our existing architecture.
|
20
|
+
|
21
|
+
For this Rails Engine, I'm not going to include a lot of the sample lower-level handlers that the standalone application has written in Rust. However, you can [checkout the writeup](https://github.com/tasker-systems/tasker_rails#technology-choices) in that app if you're interested!
|