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,601 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tasker
|
4
|
+
module Events
|
5
|
+
module Subscribers
|
6
|
+
# BaseSubscriber provides a clean foundation for creating custom event subscribers
|
7
|
+
#
|
8
|
+
# This class extracts common patterns from TelemetrySubscriber and provides:
|
9
|
+
# - Declarative subscription registration via class methods
|
10
|
+
# - Automatic method routing from event names to handler methods
|
11
|
+
# - Defensive payload handling with safe accessors
|
12
|
+
# - Easy integration with the Tasker event system
|
13
|
+
# - Metrics collection helper methods for common patterns
|
14
|
+
#
|
15
|
+
# Usage:
|
16
|
+
# class OrderNotificationSubscriber < Tasker::Events::Subscribers::BaseSubscriber
|
17
|
+
# subscribe_to :task_completed, :step_failed
|
18
|
+
#
|
19
|
+
# def handle_task_completed(event)
|
20
|
+
# OrderMailer.completion_email(event[:task_id]).deliver_later
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# def handle_step_failed(event)
|
24
|
+
# AlertService.notify("Step failed: #{event[:step_name]}")
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# # Register the subscriber
|
29
|
+
# OrderNotificationSubscriber.subscribe(Tasker::Events::Publisher.instance)
|
30
|
+
class BaseSubscriber
|
31
|
+
class_attribute :subscribed_events, instance_writer: false, default: []
|
32
|
+
class_attribute :event_filter, instance_writer: false
|
33
|
+
|
34
|
+
def initialize(name: nil, events: nil, config: {})
|
35
|
+
@subscription_name = name
|
36
|
+
@subscription_config = config
|
37
|
+
|
38
|
+
# If events are provided via constructor (from YAML), add them to subscribed events
|
39
|
+
return if events.blank?
|
40
|
+
|
41
|
+
current_events = self.class.subscribed_events || []
|
42
|
+
self.class.subscribed_events = (current_events + Array(events)).uniq
|
43
|
+
end
|
44
|
+
|
45
|
+
class << self
|
46
|
+
# Declarative method to register events this subscriber cares about
|
47
|
+
#
|
48
|
+
# @param events [Array<Symbol, String>] Event names to subscribe to
|
49
|
+
# @return [void]
|
50
|
+
#
|
51
|
+
# Example:
|
52
|
+
# subscribe_to :task_completed, :step_failed
|
53
|
+
# subscribe_to 'order.created', 'payment.processed'
|
54
|
+
def subscribe_to(*events)
|
55
|
+
# Accumulate events instead of replacing them
|
56
|
+
current_events = subscribed_events || []
|
57
|
+
self.subscribed_events = (current_events + events.map(&:to_s)).uniq
|
58
|
+
end
|
59
|
+
|
60
|
+
# Set a filter for events (optional)
|
61
|
+
#
|
62
|
+
# @param filter_proc [Proc] A proc that returns true for events to process
|
63
|
+
# @return [void]
|
64
|
+
#
|
65
|
+
# Example:
|
66
|
+
# filter_events { |event_name| event_name.include?('order') }
|
67
|
+
def filter_events(&filter_proc)
|
68
|
+
self.event_filter = filter_proc
|
69
|
+
end
|
70
|
+
|
71
|
+
# Subscribe this subscriber to a publisher
|
72
|
+
#
|
73
|
+
# @param publisher [Tasker::Events::Publisher] The event publisher
|
74
|
+
# @return [BaseSubscriber] The subscriber instance
|
75
|
+
def subscribe(publisher)
|
76
|
+
subscriber = new
|
77
|
+
subscriber.subscribe_to_publisher(publisher)
|
78
|
+
subscriber
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Subscribe to all events defined by the class
|
83
|
+
#
|
84
|
+
# @param publisher [Tasker::Events::Publisher] The event publisher
|
85
|
+
# @return [void]
|
86
|
+
def subscribe_to_publisher(publisher)
|
87
|
+
event_subscriptions.each do |event_constant, handler_method|
|
88
|
+
# Apply filtering if defined
|
89
|
+
next unless should_handle_event?(event_constant)
|
90
|
+
|
91
|
+
# Subscribe to the event with automatic method routing
|
92
|
+
# This will fail fast if the event doesn't exist, which is the correct behavior
|
93
|
+
publisher.subscribe(event_constant, &method(handler_method))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
protected
|
98
|
+
|
99
|
+
# Check if an event is a custom event (not a system constant)
|
100
|
+
#
|
101
|
+
# @param event_constant [String] The event constant or name
|
102
|
+
# @return [Boolean] Whether it's a custom event
|
103
|
+
def custom_event?(event_constant)
|
104
|
+
event_str = event_constant.to_s
|
105
|
+
event_str.exclude?('Tasker::Constants::') && event_str.include?('.')
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get event subscriptions mapping for this subscriber
|
109
|
+
#
|
110
|
+
# This method maps event constants to handler methods using naming conventions.
|
111
|
+
# Override this method to customize the mapping.
|
112
|
+
#
|
113
|
+
# @return [Hash] Mapping of event constants to handler method symbols
|
114
|
+
def event_subscriptions
|
115
|
+
@event_subscriptions ||= build_event_subscriptions
|
116
|
+
end
|
117
|
+
|
118
|
+
# Build event subscriptions using explicit constants
|
119
|
+
#
|
120
|
+
# @return [Hash] Mapping of event constants to handler method symbols
|
121
|
+
def build_event_subscriptions
|
122
|
+
subscriptions = {}
|
123
|
+
|
124
|
+
(self.class.subscribed_events || []).each do |event_name|
|
125
|
+
# Convert developer-friendly name to internal constant
|
126
|
+
internal_constant = resolve_internal_event_constant(event_name)
|
127
|
+
|
128
|
+
# Generate handler method name: order.processed -> handle_order_processed
|
129
|
+
handler_method = generate_handler_method_name(event_name)
|
130
|
+
|
131
|
+
# Only add if the handler method exists
|
132
|
+
if respond_to?(handler_method, true)
|
133
|
+
subscriptions[internal_constant] = handler_method
|
134
|
+
else
|
135
|
+
Rails.logger.warn("#{self.class.name}: Handler method #{handler_method} not found for event #{event_name}")
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
subscriptions
|
140
|
+
end
|
141
|
+
|
142
|
+
# Resolve developer-friendly event name to internal constant
|
143
|
+
#
|
144
|
+
# This handles the transparent namespace mapping:
|
145
|
+
# - "order.processed" -> "custom.order.processed" (for custom events)
|
146
|
+
# - "task.completed" -> "task.completed" (for system events)
|
147
|
+
#
|
148
|
+
# @param event_name [String] The developer-friendly event name
|
149
|
+
# @return [String] The internal event constant
|
150
|
+
def resolve_internal_event_constant(event_name)
|
151
|
+
event_str = event_name.to_s
|
152
|
+
|
153
|
+
# Check if it's already an internal constant (starts with system prefixes)
|
154
|
+
system_prefixes = %w[task. step. workflow. observability.]
|
155
|
+
if system_prefixes.any? { |prefix| event_str.start_with?(prefix) }
|
156
|
+
return event_str # It's a system event, use as-is
|
157
|
+
end
|
158
|
+
|
159
|
+
# Check if it's already prefixed with custom.
|
160
|
+
if event_str.start_with?('custom.')
|
161
|
+
return event_str # Already internal format
|
162
|
+
end
|
163
|
+
|
164
|
+
# Assume it's a custom event and add the prefix
|
165
|
+
"custom.#{event_str}"
|
166
|
+
end
|
167
|
+
|
168
|
+
# Generate handler method name from event name
|
169
|
+
#
|
170
|
+
# @param event_name [String] The event name (should be consistent format)
|
171
|
+
# @return [Symbol] The handler method name
|
172
|
+
def generate_handler_method_name(event_name)
|
173
|
+
# Convert dots to underscores and prefix with handle_
|
174
|
+
# Examples:
|
175
|
+
# 'task.completed' -> :handle_task_completed
|
176
|
+
# 'step.failed' -> :handle_step_failed
|
177
|
+
# 'custom.event' -> :handle_custom_event
|
178
|
+
clean_name = event_name.to_s.tr('.', '_').underscore
|
179
|
+
:"handle_#{clean_name}"
|
180
|
+
end
|
181
|
+
|
182
|
+
# Check if this subscriber should handle the given event
|
183
|
+
#
|
184
|
+
# @param event_constant [String] The event constant
|
185
|
+
# @return [Boolean] Whether to handle this event
|
186
|
+
def should_handle_event?(event_constant)
|
187
|
+
# Apply class-level filter if defined
|
188
|
+
return false if self.class.event_filter && !self.class.event_filter.call(event_constant)
|
189
|
+
|
190
|
+
# Apply instance-level filtering (override in subclasses)
|
191
|
+
should_process_event?(event_constant)
|
192
|
+
end
|
193
|
+
|
194
|
+
# Instance-level event filtering (override in subclasses)
|
195
|
+
#
|
196
|
+
# @param _event_constant [String] The event constant (unused in base implementation)
|
197
|
+
# @return [Boolean] Whether to handle this event
|
198
|
+
def should_process_event?(_event_constant)
|
199
|
+
true # Process all events by default
|
200
|
+
end
|
201
|
+
|
202
|
+
# Safe accessor for event payload keys with fallback values
|
203
|
+
#
|
204
|
+
# @param event [Hash, Dry::Events::Event] The event payload or event object
|
205
|
+
# @param key [Symbol, String] The key to access
|
206
|
+
# @param default [Object] The default value if key is missing
|
207
|
+
# @return [Object] The value or default
|
208
|
+
def safe_get(event, key, default = nil)
|
209
|
+
return default if event.nil?
|
210
|
+
|
211
|
+
# Handle Dry::Events::Event objects
|
212
|
+
if event.respond_to?(:payload)
|
213
|
+
payload = event.payload
|
214
|
+
return payload.fetch(key.to_sym) { payload.fetch(key.to_s, default) }
|
215
|
+
end
|
216
|
+
|
217
|
+
# Handle plain hash events
|
218
|
+
event.fetch(key.to_sym) do
|
219
|
+
event.fetch(key.to_s, default)
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
# Extract core attributes common to most events
|
224
|
+
#
|
225
|
+
# @param event [Hash, Dry::Events::Event] The event payload or event object
|
226
|
+
# @return [Hash] Core attributes
|
227
|
+
def extract_core_attributes(event)
|
228
|
+
{
|
229
|
+
task_id: safe_get(event, :task_id, 'unknown'),
|
230
|
+
step_id: safe_get(event, :step_id),
|
231
|
+
event_timestamp: safe_get(event, :timestamp, Time.current).to_s
|
232
|
+
}.compact
|
233
|
+
end
|
234
|
+
|
235
|
+
# Extract step-specific attributes (for TelemetrySubscriber compatibility)
|
236
|
+
#
|
237
|
+
# @param event [Hash, Dry::Events::Event] The event payload or event object
|
238
|
+
# @return [Hash] Step attributes
|
239
|
+
def extract_step_attributes(event)
|
240
|
+
extract_core_attributes(event).merge(
|
241
|
+
step_id: safe_get(event, :step_id),
|
242
|
+
step_name: safe_get(event, :step_name, 'unknown_step')
|
243
|
+
).compact
|
244
|
+
end
|
245
|
+
|
246
|
+
# ===============================
|
247
|
+
# METRICS COLLECTION HELPERS
|
248
|
+
# ===============================
|
249
|
+
# These methods make it easy to extract common metrics data from events
|
250
|
+
|
251
|
+
# Extract timing metrics from completion events
|
252
|
+
#
|
253
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
254
|
+
# @return [Hash] Timing metrics with default values
|
255
|
+
#
|
256
|
+
# Example:
|
257
|
+
# timing = extract_timing_metrics(event)
|
258
|
+
# StatsD.histogram('tasker.task.duration', timing[:execution_duration])
|
259
|
+
# StatsD.gauge('tasker.task.step_count', timing[:step_count])
|
260
|
+
def extract_timing_metrics(event)
|
261
|
+
{
|
262
|
+
execution_duration: safe_get(event, :execution_duration, 0.0).to_f,
|
263
|
+
started_at: safe_get(event, :started_at),
|
264
|
+
completed_at: safe_get(event, :completed_at),
|
265
|
+
step_count: safe_get(event, :total_steps, 0).to_i,
|
266
|
+
completed_steps: safe_get(event, :completed_steps, 0).to_i,
|
267
|
+
failed_steps: safe_get(event, :failed_steps, 0).to_i
|
268
|
+
}
|
269
|
+
end
|
270
|
+
|
271
|
+
# Extract error metrics from failure events
|
272
|
+
#
|
273
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
274
|
+
# @return [Hash] Error metrics with categorization
|
275
|
+
#
|
276
|
+
# Example:
|
277
|
+
# error = extract_error_metrics(event)
|
278
|
+
# StatsD.increment('tasker.errors', tags: ["error_type:#{error[:error_type]}"])
|
279
|
+
def extract_error_metrics(event)
|
280
|
+
{
|
281
|
+
error_message: safe_get(event, :error_message, 'unknown_error'),
|
282
|
+
error_class: safe_get(event, :exception_class, 'UnknownError'),
|
283
|
+
error_type: categorize_error(safe_get(event, :exception_class)),
|
284
|
+
attempt_number: safe_get(event, :attempt_number, 1).to_i,
|
285
|
+
is_retryable: safe_get(event, :retryable, false),
|
286
|
+
final_failure: safe_get(event, :attempt_number, 1).to_i >= safe_get(event, :retry_limit, 1).to_i
|
287
|
+
}
|
288
|
+
end
|
289
|
+
|
290
|
+
# Extract performance metrics for operational monitoring
|
291
|
+
#
|
292
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
293
|
+
# @return [Hash] Performance metrics
|
294
|
+
#
|
295
|
+
# Example:
|
296
|
+
# perf = extract_performance_metrics(event)
|
297
|
+
# StatsD.histogram('tasker.memory_usage', perf[:memory_usage])
|
298
|
+
def extract_performance_metrics(event)
|
299
|
+
{
|
300
|
+
memory_usage: safe_get(event, :memory_usage, 0).to_i,
|
301
|
+
cpu_time: safe_get(event, :cpu_time, 0.0).to_f,
|
302
|
+
queue_time: safe_get(event, :queue_time, 0.0).to_f,
|
303
|
+
processing_time: safe_get(event, :processing_time, 0.0).to_f,
|
304
|
+
retry_delay: safe_get(event, :retry_delay, 0.0).to_f
|
305
|
+
}
|
306
|
+
end
|
307
|
+
|
308
|
+
# Extract business metrics tags for categorization
|
309
|
+
#
|
310
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
311
|
+
# @return [Array<String>] Array of tag strings for metrics systems
|
312
|
+
#
|
313
|
+
# Example:
|
314
|
+
# tags = extract_metric_tags(event)
|
315
|
+
# StatsD.increment('tasker.task.completed', tags: tags)
|
316
|
+
def extract_metric_tags(event)
|
317
|
+
MetricTagsExtractor.extract(event)
|
318
|
+
end
|
319
|
+
|
320
|
+
# Service class to extract and build metric tags from events
|
321
|
+
# Reduces complexity by organizing tag building logic
|
322
|
+
class MetricTagsExtractor
|
323
|
+
class << self
|
324
|
+
# Extract all metric tags from event
|
325
|
+
#
|
326
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
327
|
+
# @return [Array<String>] Array of tag strings
|
328
|
+
def extract(event)
|
329
|
+
tags = []
|
330
|
+
|
331
|
+
tags.concat(extract_entity_tags(event))
|
332
|
+
tags.concat(extract_environment_tags(event))
|
333
|
+
tags.concat(extract_status_tags(event))
|
334
|
+
tags.concat(extract_business_tags(event))
|
335
|
+
|
336
|
+
tags.compact
|
337
|
+
end
|
338
|
+
|
339
|
+
private
|
340
|
+
|
341
|
+
# Extract core entity tags (task, step names)
|
342
|
+
#
|
343
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
344
|
+
# @return [Array<String>] Entity tags
|
345
|
+
def extract_entity_tags(event)
|
346
|
+
tags = []
|
347
|
+
|
348
|
+
task_name = safe_get_from_event(event, :task_name)
|
349
|
+
tags << "task:#{task_name}" if task_name && task_name != 'unknown'
|
350
|
+
|
351
|
+
step_name = safe_get_from_event(event, :step_name)
|
352
|
+
tags << "step:#{step_name}" if step_name && step_name != 'unknown_step'
|
353
|
+
|
354
|
+
tags
|
355
|
+
end
|
356
|
+
|
357
|
+
# Extract environment and source tags
|
358
|
+
#
|
359
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
360
|
+
# @return [Array<String>] Environment tags
|
361
|
+
def extract_environment_tags(event)
|
362
|
+
tags = []
|
363
|
+
|
364
|
+
tags << "environment:#{Rails.env}" if defined?(Rails)
|
365
|
+
|
366
|
+
source_system = safe_get_from_event(event, :source_system)
|
367
|
+
tags << "source:#{source_system}" if source_system
|
368
|
+
|
369
|
+
tags
|
370
|
+
end
|
371
|
+
|
372
|
+
# Extract status and retry tags
|
373
|
+
#
|
374
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
375
|
+
# @return [Array<String>] Status tags
|
376
|
+
def extract_status_tags(event)
|
377
|
+
tags = []
|
378
|
+
|
379
|
+
retryable = safe_get_from_event(event, :retryable)
|
380
|
+
tags << "retryable:#{retryable}" if retryable
|
381
|
+
|
382
|
+
attempt_number = safe_get_from_event(event, :attempt_number)
|
383
|
+
tags << "attempt:#{attempt_number}" if attempt_number
|
384
|
+
|
385
|
+
tags
|
386
|
+
end
|
387
|
+
|
388
|
+
# Extract business context tags
|
389
|
+
#
|
390
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
391
|
+
# @return [Array<String>] Business tags
|
392
|
+
def extract_business_tags(event)
|
393
|
+
tags = []
|
394
|
+
|
395
|
+
priority = safe_get_from_event(event, :priority)
|
396
|
+
tags << "priority:#{priority}" if priority
|
397
|
+
|
398
|
+
tags
|
399
|
+
end
|
400
|
+
|
401
|
+
# Safely get value from event (reuse BaseSubscriber logic)
|
402
|
+
#
|
403
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
404
|
+
# @param key [Symbol] The key to extract
|
405
|
+
# @param default [Object] Default value
|
406
|
+
# @return [Object] Extracted value
|
407
|
+
def safe_get_from_event(event, key, default = nil)
|
408
|
+
return default if event.nil?
|
409
|
+
|
410
|
+
# Handle Dry::Events::Event object
|
411
|
+
if event.respond_to?(:payload) && event.payload.respond_to?(:fetch)
|
412
|
+
payload = event.payload
|
413
|
+
return payload.fetch(key.to_sym) { payload.fetch(key.to_s, default) }
|
414
|
+
end
|
415
|
+
|
416
|
+
# Handle plain hash events
|
417
|
+
event.fetch(key.to_sym) do
|
418
|
+
event.fetch(key.to_s, default)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
end
|
422
|
+
end
|
423
|
+
|
424
|
+
# Create metric name with consistent naming convention
|
425
|
+
#
|
426
|
+
# @param base_name [String] The base metric name
|
427
|
+
# @param event_type [String] The event type (completed, failed, etc.)
|
428
|
+
# @return [String] Standardized metric name
|
429
|
+
#
|
430
|
+
# Example:
|
431
|
+
# metric_name = build_metric_name('tasker.task', 'completed')
|
432
|
+
# # => 'tasker.task.completed'
|
433
|
+
def build_metric_name(base_name, event_type)
|
434
|
+
"#{base_name}.#{event_type}".squeeze('.')
|
435
|
+
end
|
436
|
+
|
437
|
+
# Extract numeric value safely for metrics
|
438
|
+
#
|
439
|
+
# @param event [Hash, Dry::Events::Event] The event payload
|
440
|
+
# @param key [Symbol, String] The key to extract
|
441
|
+
# @param default [Numeric] The default value
|
442
|
+
# @return [Numeric] The numeric value
|
443
|
+
#
|
444
|
+
# Example:
|
445
|
+
# duration = extract_numeric_metric(event, :execution_duration, 0.0)
|
446
|
+
# StatsD.histogram('task.duration', duration)
|
447
|
+
def extract_numeric_metric(event, key, default = 0)
|
448
|
+
value = safe_get(event, key, default)
|
449
|
+
|
450
|
+
# Handle nil values and non-numeric types
|
451
|
+
return default if value.nil? || !value.respond_to?(:to_f)
|
452
|
+
|
453
|
+
# Try to convert to float
|
454
|
+
converted = value.to_f
|
455
|
+
|
456
|
+
# Check if this was a valid numeric conversion
|
457
|
+
# For strings that can't convert, to_f returns 0.0
|
458
|
+
return default if converted == 0.0 && value.is_a?(String) && value !~ /\A\s*0*(\.0*)?\s*\z/
|
459
|
+
|
460
|
+
converted
|
461
|
+
end
|
462
|
+
|
463
|
+
private
|
464
|
+
|
465
|
+
# Categorize error types for metrics tagging
|
466
|
+
#
|
467
|
+
# @param error_class [String] The exception class name
|
468
|
+
# @return [String] Categorized error type
|
469
|
+
def categorize_error(error_class)
|
470
|
+
ErrorCategorizer.categorize(error_class)
|
471
|
+
end
|
472
|
+
|
473
|
+
# Service class to categorize error types for metrics
|
474
|
+
# Reduces complexity by organizing error classification logic
|
475
|
+
class ErrorCategorizer
|
476
|
+
class << self
|
477
|
+
# Categorize error based on class name
|
478
|
+
#
|
479
|
+
# @param error_class [String] The exception class name
|
480
|
+
# @return [String] Categorized error type
|
481
|
+
def categorize(error_class)
|
482
|
+
return 'unknown' if error_class.blank?
|
483
|
+
|
484
|
+
error_string = error_class.to_s
|
485
|
+
|
486
|
+
classify_error_type(error_string)
|
487
|
+
end
|
488
|
+
|
489
|
+
private
|
490
|
+
|
491
|
+
# Classify error type using pattern matching
|
492
|
+
#
|
493
|
+
# @param error_string [String] The error class as string
|
494
|
+
# @return [String] Classified error type
|
495
|
+
def classify_error_type(error_string)
|
496
|
+
ErrorTypeClassifier.classify(error_string)
|
497
|
+
end
|
498
|
+
|
499
|
+
# Service class to classify error types using pattern matching
|
500
|
+
# Reduces complexity by organizing error type classification logic
|
501
|
+
class ErrorTypeClassifier
|
502
|
+
class << self
|
503
|
+
# Classify error type from error string
|
504
|
+
#
|
505
|
+
# @param error_string [String] The error class as string
|
506
|
+
# @return [String] Classified error type
|
507
|
+
def classify(error_string)
|
508
|
+
ERROR_TYPE_MATCHERS.each do |type, matcher|
|
509
|
+
return type if matcher.call(error_string)
|
510
|
+
end
|
511
|
+
|
512
|
+
'other'
|
513
|
+
end
|
514
|
+
|
515
|
+
# Map of error types to their matching logic
|
516
|
+
ERROR_TYPE_MATCHERS = {
|
517
|
+
'timeout' => ->(str) { timeout_error?(str) },
|
518
|
+
'network' => ->(str) { network_error?(str) },
|
519
|
+
'not_found' => ->(str) { not_found_error?(str) },
|
520
|
+
'auth' => ->(str) { auth_error?(str) },
|
521
|
+
'rate_limit' => ->(str) { rate_limit_error?(str) },
|
522
|
+
'client_error' => ->(str) { client_error?(str) },
|
523
|
+
'server_error' => ->(str) { server_error?(str) },
|
524
|
+
'runtime' => ->(str) { runtime_error?(str) }
|
525
|
+
}.freeze
|
526
|
+
|
527
|
+
# Check if error is timeout-related
|
528
|
+
#
|
529
|
+
# @param error_string [String] The error class as string
|
530
|
+
# @return [Boolean] True if timeout error
|
531
|
+
def self.timeout_error?(error_string)
|
532
|
+
error_string.match?(/Timeout/i) || error_string.match?(/TimeoutError/i)
|
533
|
+
end
|
534
|
+
|
535
|
+
# Check if error is network-related
|
536
|
+
#
|
537
|
+
# @param error_string [String] The error class as string
|
538
|
+
# @return [Boolean] True if network error
|
539
|
+
def self.network_error?(error_string)
|
540
|
+
error_string.match?(/Connection/i) || error_string.match?(/Network/i)
|
541
|
+
end
|
542
|
+
|
543
|
+
# Check if error is not found-related
|
544
|
+
#
|
545
|
+
# @param error_string [String] The error class as string
|
546
|
+
# @return [Boolean] True if not found error
|
547
|
+
def self.not_found_error?(error_string)
|
548
|
+
error_string.match?(/NotFound/i) || error_string.match?(/Missing/i) || error_string.include?('404')
|
549
|
+
end
|
550
|
+
|
551
|
+
# Check if error is authentication-related
|
552
|
+
#
|
553
|
+
# @param error_string [String] The error class as string
|
554
|
+
# @return [Boolean] True if auth error
|
555
|
+
def self.auth_error?(error_string)
|
556
|
+
error_string.match?(/Unauthorized/i) || error_string.match?(/Forbidden/i) ||
|
557
|
+
error_string.include?('401') || error_string.include?('403')
|
558
|
+
end
|
559
|
+
|
560
|
+
# Check if error is rate limit-related
|
561
|
+
#
|
562
|
+
# @param error_string [String] The error class as string
|
563
|
+
# @return [Boolean] True if rate limit error
|
564
|
+
def self.rate_limit_error?(error_string)
|
565
|
+
error_string.match?(/RateLimit/i) || error_string.match?(/TooManyRequests/i) ||
|
566
|
+
error_string.include?('429')
|
567
|
+
end
|
568
|
+
|
569
|
+
# Check if error is client error-related
|
570
|
+
#
|
571
|
+
# @param error_string [String] The error class as string
|
572
|
+
# @return [Boolean] True if client error
|
573
|
+
def self.client_error?(error_string)
|
574
|
+
error_string.match?(/BadRequest/i) || error_string.match?(/Invalid/i) ||
|
575
|
+
error_string.include?('400')
|
576
|
+
end
|
577
|
+
|
578
|
+
# Check if error is server error-related
|
579
|
+
#
|
580
|
+
# @param error_string [String] The error class as string
|
581
|
+
# @return [Boolean] True if server error
|
582
|
+
def self.server_error?(error_string)
|
583
|
+
error_string.match?(/ServerError/i) || error_string.match?(/InternalError/i) ||
|
584
|
+
error_string.include?('500')
|
585
|
+
end
|
586
|
+
|
587
|
+
# Check if error is runtime-related
|
588
|
+
#
|
589
|
+
# @param error_string [String] The error class as string
|
590
|
+
# @return [Boolean] True if runtime error
|
591
|
+
def self.runtime_error?(error_string)
|
592
|
+
error_string.match?(/StandardError/i) || error_string.match?(/RuntimeError/i)
|
593
|
+
end
|
594
|
+
end
|
595
|
+
end
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
end
|
600
|
+
end
|
601
|
+
end
|