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
@@ -0,0 +1,332 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'erb'
|
4
|
+
require 'pathname'
|
5
|
+
|
6
|
+
module Tasker
|
7
|
+
class TaskDiagram
|
8
|
+
# Colors for different step statuses
|
9
|
+
STATUS_COLORS = {
|
10
|
+
Tasker::Constants::WorkflowStepStatuses::PENDING => 'lightblue',
|
11
|
+
Tasker::Constants::WorkflowStepStatuses::IN_PROGRESS => 'lightgreen',
|
12
|
+
Tasker::Constants::WorkflowStepStatuses::COMPLETE => 'green',
|
13
|
+
Tasker::Constants::WorkflowStepStatuses::ERROR => 'red',
|
14
|
+
Tasker::Constants::WorkflowStepStatuses::CANCELLED => 'gray'
|
15
|
+
}.freeze
|
16
|
+
|
17
|
+
# Create a new task diagram
|
18
|
+
#
|
19
|
+
# @param task [Tasker::Task] The task to create a diagram for
|
20
|
+
# @param base_url [String, nil] Optional base URL for REST endpoints
|
21
|
+
# @return [TaskDiagram] A new task diagram instance
|
22
|
+
def initialize(task, base_url = nil)
|
23
|
+
@task = task
|
24
|
+
@base_url = base_url
|
25
|
+
end
|
26
|
+
|
27
|
+
# Generate a Mermaid diagram string for the task
|
28
|
+
#
|
29
|
+
# @return [String] Mermaid flowchart diagram string
|
30
|
+
delegate :to_mermaid, to: :flowchart
|
31
|
+
|
32
|
+
# Generate a complete HTML document with embedded Mermaid diagram
|
33
|
+
#
|
34
|
+
# @return [String] HTML document with Mermaid diagram
|
35
|
+
def to_html
|
36
|
+
# Generate the mermaid diagram
|
37
|
+
@diagram = flowchart.to_mermaid
|
38
|
+
|
39
|
+
# Create binding with relevant variables
|
40
|
+
task = @task # Make task available to the template
|
41
|
+
diagram = @diagram # Make diagram available to the template
|
42
|
+
|
43
|
+
# Create a binding with the variables
|
44
|
+
b = binding
|
45
|
+
|
46
|
+
# Get the template path relative to this file
|
47
|
+
template_path = views_path.join('_diagram.html.erb')
|
48
|
+
|
49
|
+
# Load and render the template with ERB
|
50
|
+
begin
|
51
|
+
template = File.read(template_path)
|
52
|
+
ERB.new(template).result(b)
|
53
|
+
rescue Errno::ENOENT
|
54
|
+
raise TaskDiagramError, "Template file not found: #{template_path}"
|
55
|
+
rescue Errno::EACCES
|
56
|
+
raise TaskDiagramError, "Permission denied while accessing template file: #{template_path}"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_json(pretty: false)
|
61
|
+
flowchart.to_json(pretty: pretty)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def flowchart
|
67
|
+
return @flowchart if @flowchart
|
68
|
+
|
69
|
+
# Preload workflow steps with scenic view relationships for efficiency
|
70
|
+
workflow_steps = @task.workflow_steps.includes(:named_step, :step_dag_relationship)
|
71
|
+
|
72
|
+
# Create a new flowchart
|
73
|
+
@flowchart = Tasker::Diagram::Flowchart.new(
|
74
|
+
direction: 'TD',
|
75
|
+
title: "Task #{@task.task_id}: #{@task.name}"
|
76
|
+
)
|
77
|
+
|
78
|
+
# Add task info node
|
79
|
+
@flowchart.add_node(build_task_node)
|
80
|
+
|
81
|
+
# Build nodes for all workflow steps
|
82
|
+
workflow_steps.each do |step|
|
83
|
+
@flowchart.add_node(build_step_node(step))
|
84
|
+
end
|
85
|
+
|
86
|
+
# Build all edges efficiently using scenic view data
|
87
|
+
build_all_step_edges(workflow_steps).each do |edge|
|
88
|
+
@flowchart.add_edge(edge)
|
89
|
+
end
|
90
|
+
|
91
|
+
@flowchart
|
92
|
+
end
|
93
|
+
|
94
|
+
# Get the path to the view templates directory
|
95
|
+
#
|
96
|
+
# @return [Pathname] Path to view templates
|
97
|
+
def views_path
|
98
|
+
# Get the absolute path of the current file
|
99
|
+
current_file = Pathname.new(__FILE__)
|
100
|
+
|
101
|
+
# Navigate to the views directory relative to this file
|
102
|
+
# This file is in app/models/tasker/task_diagram.rb
|
103
|
+
# Views are in app/views/tasker/task/
|
104
|
+
current_file.dirname.parent.parent.parent.join('app', 'views', 'tasker', 'task')
|
105
|
+
end
|
106
|
+
|
107
|
+
# Build the task information node
|
108
|
+
#
|
109
|
+
# @return [Tasker::Diagram::Node] The task node
|
110
|
+
def build_task_node
|
111
|
+
Tasker::Diagram::Node.new(
|
112
|
+
id: "task_#{@task.task_id}",
|
113
|
+
label: "Task: #{@task.name}\nID: #{@task.task_id}\nStatus: #{@task.status}"
|
114
|
+
)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Build a node for a workflow step
|
118
|
+
#
|
119
|
+
# @param step [Tasker::WorkflowStep] The workflow step
|
120
|
+
# @return [Tasker::Diagram::Node] The step node
|
121
|
+
def build_step_node(step)
|
122
|
+
node_id = "step_#{step.workflow_step_id}"
|
123
|
+
color = STATUS_COLORS[step.status] || 'lightgray'
|
124
|
+
|
125
|
+
# Create label with step details
|
126
|
+
label = build_step_label(step)
|
127
|
+
|
128
|
+
# Create clickable URL if base_url is provided
|
129
|
+
url = @base_url ? "#{@base_url}/tasks/#{@task.task_id}/workflow_steps/#{step.workflow_step_id}" : nil
|
130
|
+
|
131
|
+
# Create node with styling
|
132
|
+
Tasker::Diagram::Node.new(
|
133
|
+
id: node_id,
|
134
|
+
label: label.join("\n"),
|
135
|
+
shape: 'box',
|
136
|
+
style: "fill:#{color};",
|
137
|
+
url: url
|
138
|
+
)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Build the label lines for a step node
|
142
|
+
#
|
143
|
+
# @param step [Tasker::WorkflowStep] The workflow step
|
144
|
+
# @return [Array<String>] Array of label lines
|
145
|
+
def build_step_label(step)
|
146
|
+
label = [
|
147
|
+
"Step: #{step.name}",
|
148
|
+
"Status: #{step.status}",
|
149
|
+
"Attempts: #{step.attempts || 0}"
|
150
|
+
]
|
151
|
+
|
152
|
+
# Add error info if applicable
|
153
|
+
if step.status == Tasker::Constants::WorkflowStepStatuses::ERROR && step.results&.key?('error')
|
154
|
+
error_msg = step.results['error'].to_s
|
155
|
+
# Truncate long error messages
|
156
|
+
error_msg = "#{error_msg[0..27]}..." if error_msg.length > 30
|
157
|
+
label << "Error: #{error_msg}"
|
158
|
+
end
|
159
|
+
|
160
|
+
label
|
161
|
+
end
|
162
|
+
|
163
|
+
# Build an edge between two nodes
|
164
|
+
#
|
165
|
+
# @param source_id [String] The source node ID
|
166
|
+
# @param target_id [String] The target node ID
|
167
|
+
# @param label [String] The edge label
|
168
|
+
# @return [Tasker::Diagram::Edge] The edge
|
169
|
+
def build_edge(source_id, target_id, label = '')
|
170
|
+
Tasker::Diagram::Edge.new(
|
171
|
+
source_id: source_id,
|
172
|
+
target_id: target_id,
|
173
|
+
label: label
|
174
|
+
)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Build all edges efficiently using scenic view data - eliminates N+1 queries
|
178
|
+
#
|
179
|
+
# @param workflow_steps [Array<Tasker::WorkflowStep>] All workflow steps for the task
|
180
|
+
# @return [Array<Tasker::Diagram::Edge>] All edges for the diagram
|
181
|
+
def build_all_step_edges(workflow_steps)
|
182
|
+
edges = []
|
183
|
+
|
184
|
+
# Add edges from task to root steps using dedicated builder
|
185
|
+
edges.concat(TaskToRootStepEdgeBuilder.build(@task, workflow_steps))
|
186
|
+
|
187
|
+
# Add edges between steps using dedicated builder
|
188
|
+
edges.concat(StepToStepEdgeBuilder.build(workflow_steps))
|
189
|
+
|
190
|
+
edges
|
191
|
+
end
|
192
|
+
|
193
|
+
# Service class to build edges from task to root steps
|
194
|
+
# Reduces complexity by organizing edge building logic
|
195
|
+
class TaskToRootStepEdgeBuilder
|
196
|
+
class << self
|
197
|
+
# Build edges from task node to root steps
|
198
|
+
#
|
199
|
+
# @param task [Tasker::Task] The task
|
200
|
+
# @param workflow_steps [Array<Tasker::WorkflowStep>] All workflow steps
|
201
|
+
# @return [Array<Tasker::Diagram::Edge>] Task to root step edges
|
202
|
+
def build(task, workflow_steps)
|
203
|
+
edges = []
|
204
|
+
|
205
|
+
workflow_steps.each do |step|
|
206
|
+
next unless step.step_dag_relationship&.is_root_step
|
207
|
+
|
208
|
+
edges << build_edge(
|
209
|
+
"task_#{task.task_id}",
|
210
|
+
"step_#{step.workflow_step_id}"
|
211
|
+
)
|
212
|
+
end
|
213
|
+
|
214
|
+
edges
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
|
219
|
+
# Build an edge between two nodes
|
220
|
+
#
|
221
|
+
# @param source_id [String] The source node ID
|
222
|
+
# @param target_id [String] The target node ID
|
223
|
+
# @param label [String] The edge label
|
224
|
+
# @return [Tasker::Diagram::Edge] The edge
|
225
|
+
def build_edge(source_id, target_id, label = '')
|
226
|
+
Tasker::Diagram::Edge.new(
|
227
|
+
source_id: source_id,
|
228
|
+
target_id: target_id,
|
229
|
+
label: label
|
230
|
+
)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
# Service class to build edges between workflow steps
|
236
|
+
# Reduces complexity by organizing edge building logic
|
237
|
+
class StepToStepEdgeBuilder
|
238
|
+
class << self
|
239
|
+
# Build edges between workflow steps
|
240
|
+
#
|
241
|
+
# @param workflow_steps [Array<Tasker::WorkflowStep>] All workflow steps
|
242
|
+
# @return [Array<Tasker::Diagram::Edge>] Step to step edges
|
243
|
+
def build(workflow_steps)
|
244
|
+
edge_data = collect_edge_data(workflow_steps)
|
245
|
+
return [] if edge_data.empty?
|
246
|
+
|
247
|
+
edge_records = batch_load_edge_records(edge_data)
|
248
|
+
build_edges_from_data(edge_data, edge_records)
|
249
|
+
end
|
250
|
+
|
251
|
+
private
|
252
|
+
|
253
|
+
# Collect all edge relationships for efficient batch lookup
|
254
|
+
#
|
255
|
+
# @param workflow_steps [Array<Tasker::WorkflowStep>] All workflow steps
|
256
|
+
# @return [Array<Hash>] Edge data with from_step_id and to_step_id
|
257
|
+
def collect_edge_data(workflow_steps)
|
258
|
+
edge_data = []
|
259
|
+
|
260
|
+
workflow_steps.each do |step|
|
261
|
+
next unless step.step_dag_relationship
|
262
|
+
|
263
|
+
child_ids = step.step_dag_relationship.child_step_ids_array
|
264
|
+
child_ids.each do |child_id|
|
265
|
+
edge_data << {
|
266
|
+
from_step_id: step.workflow_step_id,
|
267
|
+
to_step_id: child_id
|
268
|
+
}
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
edge_data
|
273
|
+
end
|
274
|
+
|
275
|
+
# Batch load all WorkflowStepEdge records for edge labels
|
276
|
+
#
|
277
|
+
# @param edge_data [Array<Hash>] Edge data to load records for
|
278
|
+
# @return [Hash] Hash mapping edge keys to edge records
|
279
|
+
def batch_load_edge_records(edge_data)
|
280
|
+
edge_records = {}
|
281
|
+
|
282
|
+
conditions = edge_data.map do |data|
|
283
|
+
"(from_step_id = #{data[:from_step_id]} AND to_step_id = #{data[:to_step_id]})"
|
284
|
+
end
|
285
|
+
|
286
|
+
Tasker::WorkflowStepEdge.where(conditions.join(' OR ')).find_each do |edge_record|
|
287
|
+
key = "#{edge_record.from_step_id}_#{edge_record.to_step_id}"
|
288
|
+
edge_records[key] = edge_record
|
289
|
+
end
|
290
|
+
|
291
|
+
edge_records
|
292
|
+
end
|
293
|
+
|
294
|
+
# Build edges using pre-calculated data and records
|
295
|
+
#
|
296
|
+
# @param edge_data [Array<Hash>] Edge data with IDs
|
297
|
+
# @param edge_records [Hash] Loaded edge records for labels
|
298
|
+
# @return [Array<Tasker::Diagram::Edge>] Built edges
|
299
|
+
def build_edges_from_data(edge_data, edge_records)
|
300
|
+
edges = []
|
301
|
+
|
302
|
+
edge_data.each do |data|
|
303
|
+
source_id = "step_#{data[:from_step_id]}"
|
304
|
+
target_id = "step_#{data[:to_step_id]}"
|
305
|
+
|
306
|
+
# Find edge label from batch-loaded records
|
307
|
+
key = "#{data[:from_step_id]}_#{data[:to_step_id]}"
|
308
|
+
edge_label = edge_records[key]&.name || ''
|
309
|
+
|
310
|
+
edges << build_edge(source_id, target_id, edge_label)
|
311
|
+
end
|
312
|
+
|
313
|
+
edges
|
314
|
+
end
|
315
|
+
|
316
|
+
# Build an edge between two nodes
|
317
|
+
#
|
318
|
+
# @param source_id [String] The source node ID
|
319
|
+
# @param target_id [String] The target node ID
|
320
|
+
# @param label [String] The edge label
|
321
|
+
# @return [Tasker::Diagram::Edge] The edge
|
322
|
+
def build_edge(source_id, target_id, label = '')
|
323
|
+
Tasker::Diagram::Edge.new(
|
324
|
+
source_id: source_id,
|
325
|
+
target_id: target_id,
|
326
|
+
label: label
|
327
|
+
)
|
328
|
+
end
|
329
|
+
end
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tasker
|
4
|
+
# TaskExecutionContext now uses SQL functions for high-performance queries
|
5
|
+
# This class explicitly delegates to the function-based implementation for better maintainability
|
6
|
+
class TaskExecutionContext
|
7
|
+
# Explicit delegation of class methods to function-based implementation
|
8
|
+
def self.find(task_id)
|
9
|
+
Tasker::Functions::FunctionBasedTaskExecutionContext.find(task_id)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.for_tasks(task_ids)
|
13
|
+
Tasker::Functions::FunctionBasedTaskExecutionContext.for_tasks(task_ids)
|
14
|
+
end
|
15
|
+
|
16
|
+
# For backward compatibility, maintain the active method but point to function-based implementation
|
17
|
+
def self.active
|
18
|
+
Tasker::Functions::FunctionBasedTaskExecutionContext
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(task_id)
|
22
|
+
@task_id = task_id
|
23
|
+
end
|
24
|
+
|
25
|
+
def workflow_summary
|
26
|
+
@workflow_summary ||= Tasker::Functions::FunctionBasedTaskExecutionContext.find(@task_id).workflow_summary
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
# == Schema Information
|
5
|
+
#
|
6
|
+
# Table name: tasker_task_namespaces
|
7
|
+
#
|
8
|
+
# name :string(64) not null
|
9
|
+
# description :string(255)
|
10
|
+
# created_at :datetime not null
|
11
|
+
# updated_at :datetime not null
|
12
|
+
# task_namespace_id :integer not null, primary key
|
13
|
+
#
|
14
|
+
# Indexes
|
15
|
+
#
|
16
|
+
# task_namespaces_name_index (name)
|
17
|
+
# task_namespaces_name_unique (name) UNIQUE
|
18
|
+
#
|
19
|
+
module Tasker
|
20
|
+
class TaskNamespace < ApplicationRecord
|
21
|
+
self.primary_key = :task_namespace_id
|
22
|
+
|
23
|
+
has_many :named_tasks, dependent: :nullify
|
24
|
+
|
25
|
+
validates :name, presence: true, uniqueness: true, length: { maximum: 64 }
|
26
|
+
validates :description, length: { maximum: 255 }
|
27
|
+
|
28
|
+
# Find or create default namespace - always works even if not seeded
|
29
|
+
def self.default
|
30
|
+
find_or_create_by!(name: 'default')
|
31
|
+
end
|
32
|
+
|
33
|
+
# Scope for non-default namespaces
|
34
|
+
scope :custom, -> { where.not(name: 'default') }
|
35
|
+
|
36
|
+
# Check if this is the default namespace
|
37
|
+
def default?
|
38
|
+
name == 'default'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,235 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tasker
|
4
|
+
# TaskTransition represents state transitions for Task entities using Statesman
|
5
|
+
#
|
6
|
+
# This model stores the audit trail of all task state changes, providing
|
7
|
+
# a complete history of task lifecycle events with metadata and timestamps.
|
8
|
+
class TaskTransition < ApplicationRecord
|
9
|
+
# NOTE: We don't include Statesman::Adapters::ActiveRecordTransition
|
10
|
+
# because we're using PostgreSQL JSONB column for metadata
|
11
|
+
|
12
|
+
# Associations
|
13
|
+
belongs_to :task, inverse_of: :task_transitions
|
14
|
+
|
15
|
+
# Validations
|
16
|
+
validates :to_state, inclusion: {
|
17
|
+
in: %w[pending in_progress complete error cancelled resolved_manually],
|
18
|
+
message: 'is not a valid task state'
|
19
|
+
}
|
20
|
+
|
21
|
+
# Validate that the task exists before creating transition
|
22
|
+
validate :task_must_exist
|
23
|
+
|
24
|
+
validates :sort_key, presence: true, uniqueness: { scope: :task_id }
|
25
|
+
# Custom validation for metadata that allows empty hash but not nil
|
26
|
+
validate :metadata_must_be_hash
|
27
|
+
|
28
|
+
# Ensure metadata is always a hash
|
29
|
+
after_initialize :ensure_metadata_hash
|
30
|
+
# Ensure metadata defaults to empty hash if not provided
|
31
|
+
before_validation :ensure_metadata_presence
|
32
|
+
|
33
|
+
# Scopes
|
34
|
+
scope :recent, -> { order(sort_key: :desc) }
|
35
|
+
scope :to_state, ->(state) { where(to_state: state) }
|
36
|
+
scope :with_metadata_key, ->(key) { where('metadata ? :key', key: key.to_s) }
|
37
|
+
|
38
|
+
# Class methods for querying transitions
|
39
|
+
class << self
|
40
|
+
# Find the most recent transition to a specific state
|
41
|
+
#
|
42
|
+
# @param state [String, Symbol] The state to find the most recent transition to
|
43
|
+
# @return [TaskTransition, nil] The most recent transition to the given state
|
44
|
+
def most_recent_to_state(state)
|
45
|
+
to_state(state.to_s).order(sort_key: :desc).first
|
46
|
+
end
|
47
|
+
|
48
|
+
# Find all transitions that occurred within a time range
|
49
|
+
#
|
50
|
+
# @param start_time [Time] The start of the time range
|
51
|
+
# @param end_time [Time] The end of the time range
|
52
|
+
# @return [ActiveRecord::Relation] Transitions within the time range
|
53
|
+
def in_time_range(start_time, end_time)
|
54
|
+
where(created_at: start_time..end_time)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Find transitions with specific metadata values
|
58
|
+
#
|
59
|
+
# @param key [String, Symbol] The metadata key to search for
|
60
|
+
# @param value [Object] The value to match
|
61
|
+
# @return [ActiveRecord::Relation] Transitions with matching metadata
|
62
|
+
def with_metadata_value(key, value)
|
63
|
+
where('metadata->:key = :value', key: key.to_s, value: value.to_json.delete('"'))
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get transition statistics for analytics
|
67
|
+
#
|
68
|
+
# @return [Hash] Statistics about transitions
|
69
|
+
def statistics
|
70
|
+
{
|
71
|
+
total_transitions: count,
|
72
|
+
states: group(:to_state).count,
|
73
|
+
recent_activity: where(created_at: 24.hours.ago..Time.current).count,
|
74
|
+
average_time_between_transitions: average_time_between_transitions
|
75
|
+
}
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Calculate average time between transitions
|
81
|
+
#
|
82
|
+
# @return [Float, nil] Average seconds between transitions
|
83
|
+
def average_time_between_transitions
|
84
|
+
transitions = order(:created_at).pluck(:created_at)
|
85
|
+
return nil if transitions.size < 2
|
86
|
+
|
87
|
+
total_time = 0
|
88
|
+
(1...transitions.size).each do |i|
|
89
|
+
total_time += (transitions[i] - transitions[i - 1])
|
90
|
+
end
|
91
|
+
|
92
|
+
total_time / (transitions.size - 1)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Instance methods
|
97
|
+
|
98
|
+
# Get the duration since the previous transition
|
99
|
+
#
|
100
|
+
# @return [Float, nil] Duration in seconds since previous transition
|
101
|
+
def duration_since_previous
|
102
|
+
previous_transition = self.class.where(task_id: task_id)
|
103
|
+
.where(sort_key: ...sort_key)
|
104
|
+
.order(sort_key: :desc)
|
105
|
+
.first
|
106
|
+
|
107
|
+
return nil unless previous_transition
|
108
|
+
|
109
|
+
created_at - previous_transition.created_at
|
110
|
+
end
|
111
|
+
|
112
|
+
# Check if this transition represents an error state
|
113
|
+
#
|
114
|
+
# @return [Boolean] True if transitioning to an error state
|
115
|
+
def error_transition?
|
116
|
+
to_state == 'error'
|
117
|
+
end
|
118
|
+
|
119
|
+
# Check if this transition represents completion
|
120
|
+
#
|
121
|
+
# @return [Boolean] True if transitioning to a completion state
|
122
|
+
def completion_transition?
|
123
|
+
%w[complete resolved_manually].include?(to_state)
|
124
|
+
end
|
125
|
+
|
126
|
+
# Check if this transition represents cancellation
|
127
|
+
#
|
128
|
+
# @return [Boolean] True if transitioning to cancelled state
|
129
|
+
def cancellation_transition?
|
130
|
+
to_state == 'cancelled'
|
131
|
+
end
|
132
|
+
|
133
|
+
# Get human-readable description of the transition
|
134
|
+
#
|
135
|
+
# @return [String] Description of what this transition represents
|
136
|
+
def description
|
137
|
+
case to_state
|
138
|
+
when 'pending'
|
139
|
+
'Task initialized and ready for processing'
|
140
|
+
when 'in_progress'
|
141
|
+
'Task execution started'
|
142
|
+
when 'complete'
|
143
|
+
'Task completed successfully'
|
144
|
+
when 'error'
|
145
|
+
'Task encountered an error'
|
146
|
+
when 'cancelled'
|
147
|
+
'Task was cancelled'
|
148
|
+
when 'resolved_manually'
|
149
|
+
'Task was manually resolved'
|
150
|
+
else
|
151
|
+
"Task transitioned to #{to_state}"
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# Get formatted metadata for display
|
156
|
+
#
|
157
|
+
# @return [Hash] Formatted metadata with additional computed fields
|
158
|
+
def formatted_metadata
|
159
|
+
base_metadata = metadata.dup
|
160
|
+
|
161
|
+
# Add computed fields
|
162
|
+
base_metadata['duration_since_previous'] = duration_since_previous
|
163
|
+
base_metadata['transition_description'] = description
|
164
|
+
base_metadata['transition_timestamp'] = created_at.iso8601
|
165
|
+
|
166
|
+
base_metadata
|
167
|
+
end
|
168
|
+
|
169
|
+
# Check if transition has specific metadata
|
170
|
+
#
|
171
|
+
# @param key [String, Symbol] The metadata key to check for
|
172
|
+
# @return [Boolean] True if the metadata contains the key
|
173
|
+
def has_metadata?(key)
|
174
|
+
metadata.key?(key.to_s)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Get metadata value with default
|
178
|
+
#
|
179
|
+
# @param key [String, Symbol] The metadata key
|
180
|
+
# @param default [Object] Default value if key not found
|
181
|
+
# @return [Object] The metadata value or default
|
182
|
+
def get_metadata(key, default = nil)
|
183
|
+
metadata.fetch(key.to_s, default)
|
184
|
+
end
|
185
|
+
|
186
|
+
# Set metadata value
|
187
|
+
#
|
188
|
+
# @param key [String, Symbol] The metadata key
|
189
|
+
# @param value [Object] The value to set
|
190
|
+
# @return [Object] The set value
|
191
|
+
def set_metadata(key, value)
|
192
|
+
self.metadata = metadata.merge(key.to_s => value)
|
193
|
+
value
|
194
|
+
end
|
195
|
+
|
196
|
+
private
|
197
|
+
|
198
|
+
# Ensure metadata is always initialized as a hash
|
199
|
+
#
|
200
|
+
# @return [void]
|
201
|
+
def ensure_metadata_hash
|
202
|
+
self.metadata ||= {}
|
203
|
+
end
|
204
|
+
|
205
|
+
# Ensure metadata is present for validation
|
206
|
+
#
|
207
|
+
# @return [void]
|
208
|
+
def ensure_metadata_presence
|
209
|
+
self.metadata = {} if metadata.blank?
|
210
|
+
end
|
211
|
+
|
212
|
+
# Custom validation for metadata
|
213
|
+
#
|
214
|
+
# @return [void]
|
215
|
+
def metadata_must_be_hash
|
216
|
+
if metadata.nil?
|
217
|
+
self.metadata = {}
|
218
|
+
elsif !metadata.is_a?(Hash)
|
219
|
+
errors.add(:metadata, 'must be a hash')
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Validate that the task exists
|
224
|
+
#
|
225
|
+
# @return [void]
|
226
|
+
def task_must_exist
|
227
|
+
return if task_id.blank?
|
228
|
+
|
229
|
+
errors.add(:task, 'must exist before creating transition') unless Tasker::Task.exists?(task_id: task_id)
|
230
|
+
rescue ActiveRecord::StatementInvalid => e
|
231
|
+
# Handle cases where the table might not exist (e.g., during migrations)
|
232
|
+
Rails.logger.warn { "Could not validate task existence: #{e.message}" }
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|