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,322 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'events/custom_registry'
|
5
|
+
require_relative 'registry/base_registry'
|
6
|
+
require_relative 'registry/interface_validator'
|
7
|
+
require 'concurrent-ruby'
|
8
|
+
|
9
|
+
module Tasker
|
10
|
+
# Factory for creating task handler instances
|
11
|
+
#
|
12
|
+
# This class maintains a registry of task handlers by name and dependent system,
|
13
|
+
# providing namespaced handler organization while maintaining backward compatibility.
|
14
|
+
# It follows the Singleton pattern to ensure a single registry and uses thread-safe
|
15
|
+
# storage with modern registry patterns.
|
16
|
+
class HandlerFactory < Registry::BaseRegistry
|
17
|
+
include Singleton
|
18
|
+
|
19
|
+
# @return [Concurrent::Hash] Thread-safe registered handler classes by dependent system and handler name
|
20
|
+
attr_reader :handler_classes
|
21
|
+
|
22
|
+
# @return [Set] Set of registered namespaces for efficient enumeration
|
23
|
+
attr_reader :namespaces
|
24
|
+
|
25
|
+
# Initialize a new handler factory
|
26
|
+
#
|
27
|
+
# @return [HandlerFactory] A new handler factory instance
|
28
|
+
def initialize
|
29
|
+
super
|
30
|
+
@handler_classes = Concurrent::Hash.new
|
31
|
+
@namespaces = Set.new([:default])
|
32
|
+
log_registry_operation('initialized', namespaces: @namespaces.to_a)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get a task handler instance by name and optional dependent system
|
36
|
+
#
|
37
|
+
# @param name [String, Symbol] The name of the handler to retrieve
|
38
|
+
# @param namespace_name [String, Symbol] The dependent system namespace (defaults to 'default')
|
39
|
+
# @param version [String] The version of the handler (defaults to '0.1.0')
|
40
|
+
# @return [Object] An instance of the requested task handler
|
41
|
+
# @raise [Tasker::ProceduralError] If no handler is registered with the given name in the specified system
|
42
|
+
def get(name, namespace_name: :default, version: '0.1.0')
|
43
|
+
namespace_name = namespace_name.to_sym
|
44
|
+
name_sym = name.to_sym
|
45
|
+
|
46
|
+
thread_safe_operation do
|
47
|
+
# Direct namespace lookup - allows same name in different systems
|
48
|
+
handler_class = @handler_classes.dig(namespace_name, name_sym, version)
|
49
|
+
raise_handler_not_found(name, namespace_name, version) unless handler_class
|
50
|
+
|
51
|
+
log_registry_operation('handler_retrieved',
|
52
|
+
entity_type: 'task_handler',
|
53
|
+
entity_id: "#{namespace_name}/#{name_sym}/#{version}",
|
54
|
+
handler_class: handler_class.is_a?(Class) ? handler_class.name : handler_class)
|
55
|
+
|
56
|
+
instantiate_handler(handler_class)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# Register a task handler class with a name and optional dependent system
|
61
|
+
#
|
62
|
+
# @param name [String, Symbol] The name to register the handler under
|
63
|
+
# @param class_or_class_name [Class, String] The handler class to register
|
64
|
+
# @param namespace_name [String, Symbol] The dependent system namespace (defaults to 'default')
|
65
|
+
# @param version [String] The version of the handler (defaults to '0.1.0')
|
66
|
+
# @param options [Hash] Additional registration options
|
67
|
+
# @option options [Boolean] :replace (false) Whether to replace existing handler
|
68
|
+
# @return [Boolean] True if registration successful
|
69
|
+
# @raise [StandardError] If custom event configuration fails (fail fast)
|
70
|
+
# @raise [ArgumentError] If handler already exists and replace is false
|
71
|
+
def register(name, class_or_class_name, namespace_name: :default, version: '0.1.0', **options)
|
72
|
+
name_sym = name.to_sym
|
73
|
+
namespace_name = namespace_name.to_sym
|
74
|
+
replace = options.fetch(:replace, false)
|
75
|
+
|
76
|
+
thread_safe_operation do
|
77
|
+
# Validate custom event configuration BEFORE modifying registry state
|
78
|
+
# This ensures atomic registration - either fully succeeds or fully fails
|
79
|
+
normalized_class = normalize_class_name(class_or_class_name)
|
80
|
+
|
81
|
+
# Validate handler interface using unified validator
|
82
|
+
begin
|
83
|
+
Registry::InterfaceValidator.validate_handler!(normalized_class.is_a?(Class) ? normalized_class : normalized_class.constantize)
|
84
|
+
rescue ArgumentError => e
|
85
|
+
log_validation_failure('task_handler', "#{namespace_name}/#{name_sym}/#{version}", e.message)
|
86
|
+
raise
|
87
|
+
end
|
88
|
+
|
89
|
+
discover_and_register_custom_events(class_or_class_name)
|
90
|
+
|
91
|
+
# Initialize nested hash structure
|
92
|
+
@handler_classes[namespace_name] ||= Concurrent::Hash.new
|
93
|
+
@handler_classes[namespace_name][name_sym] ||= Concurrent::Hash.new
|
94
|
+
|
95
|
+
# Check for existing handler
|
96
|
+
entity_id = "#{namespace_name}/#{name_sym}/#{version}"
|
97
|
+
if @handler_classes[namespace_name][name_sym].key?(version) && !replace
|
98
|
+
raise ArgumentError,
|
99
|
+
"Handler '#{name_sym}' already registered in namespace '#{namespace_name}' version '#{version}'. Use replace: true to override."
|
100
|
+
end
|
101
|
+
|
102
|
+
# Log replacement if needed
|
103
|
+
if @handler_classes[namespace_name][name_sym].key?(version)
|
104
|
+
existing_class = @handler_classes[namespace_name][name_sym][version]
|
105
|
+
log_unregistration('task_handler', entity_id,
|
106
|
+
existing_class.is_a?(Class) ? existing_class : existing_class.constantize)
|
107
|
+
end
|
108
|
+
|
109
|
+
# Register handler
|
110
|
+
@handler_classes[namespace_name][name_sym][version] = normalized_class
|
111
|
+
@namespaces.add(namespace_name)
|
112
|
+
|
113
|
+
# Log successful registration
|
114
|
+
log_registration('task_handler', entity_id,
|
115
|
+
normalized_class.is_a?(Class) ? normalized_class : normalized_class.constantize,
|
116
|
+
{ namespace_name: namespace_name, version: version, **options })
|
117
|
+
|
118
|
+
true
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
# List handlers, optionally filtered by namespace
|
123
|
+
#
|
124
|
+
# @param namespace [String, Symbol, nil] Optional namespace filter
|
125
|
+
# @return [Hash] Handlers hash, either for specific namespace or all namespaces
|
126
|
+
def list_handlers(namespace: nil)
|
127
|
+
if namespace
|
128
|
+
@handler_classes[namespace.to_sym] || Concurrent::Hash.new
|
129
|
+
else
|
130
|
+
@handler_classes.dup
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Get list of all registered namespaces
|
135
|
+
#
|
136
|
+
# @return [Array<Symbol>] Array of namespace symbols
|
137
|
+
def registered_namespaces
|
138
|
+
@namespaces.to_a
|
139
|
+
end
|
140
|
+
|
141
|
+
# Get comprehensive registry statistics
|
142
|
+
#
|
143
|
+
# @return [Hash] Detailed statistics about the registry
|
144
|
+
def stats
|
145
|
+
base_stats.merge(
|
146
|
+
total_namespaces: @namespaces.size,
|
147
|
+
total_handlers: count_total_handlers,
|
148
|
+
handlers_by_namespace: count_handlers_by_namespace,
|
149
|
+
versions_by_namespace: count_versions_by_namespace
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
# Get all registered handlers (required by BaseRegistry)
|
154
|
+
#
|
155
|
+
# @return [Hash] All registered handlers
|
156
|
+
def all_items
|
157
|
+
@handler_classes.dup
|
158
|
+
end
|
159
|
+
|
160
|
+
# Clear all registered handlers (required by BaseRegistry)
|
161
|
+
#
|
162
|
+
# @return [Boolean] True if cleared successfully
|
163
|
+
def clear!
|
164
|
+
clear_all!
|
165
|
+
end
|
166
|
+
|
167
|
+
# Clear all registered handlers (for testing)
|
168
|
+
#
|
169
|
+
# @return [Boolean] True if cleared successfully
|
170
|
+
def clear_all!
|
171
|
+
thread_safe_operation do
|
172
|
+
@handler_classes.clear
|
173
|
+
@namespaces = Set.new([:default])
|
174
|
+
log_registry_operation('cleared_all')
|
175
|
+
true
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
private
|
180
|
+
|
181
|
+
# Normalize class name for consistent storage
|
182
|
+
#
|
183
|
+
# @param class_or_class_name [Class, String] The handler class to normalize
|
184
|
+
# @return [Class, String] Normalized class representation
|
185
|
+
def normalize_class_name(class_or_class_name)
|
186
|
+
if class_or_class_name.is_a?(Class)
|
187
|
+
# Store the class directly for anonymous classes
|
188
|
+
class_or_class_name
|
189
|
+
else
|
190
|
+
# Store as string for named classes (original behavior)
|
191
|
+
class_or_class_name.to_s
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
# Instantiate a handler from class or string
|
196
|
+
#
|
197
|
+
# @param handler_class [Class, String] The handler class to instantiate
|
198
|
+
# @return [Object] New handler instance
|
199
|
+
# @raise [Tasker::ProceduralError] If handler class cannot be instantiated
|
200
|
+
def instantiate_handler(handler_class)
|
201
|
+
if handler_class.is_a?(Class)
|
202
|
+
# Direct class instantiation (used in tests with anonymous classes)
|
203
|
+
handler_class.new
|
204
|
+
else
|
205
|
+
# String class name instantiation (used in production)
|
206
|
+
handler_class.to_s.camelize.constantize.new
|
207
|
+
end
|
208
|
+
rescue NameError => e
|
209
|
+
error_msg = "Failed to instantiate handler: #{e.message}"
|
210
|
+
log_registry_error('handler_instantiation', e, handler_class: handler_class)
|
211
|
+
raise(Tasker::ProceduralError, error_msg)
|
212
|
+
end
|
213
|
+
|
214
|
+
# Raise appropriate error for handler not found
|
215
|
+
#
|
216
|
+
# @param name [String, Symbol] Handler name that was not found
|
217
|
+
# @param namespace_name [Symbol] The namespace that was searched
|
218
|
+
# @param version [String] The version that was searched
|
219
|
+
# @raise [Tasker::ProceduralError] Handler not found error
|
220
|
+
def raise_handler_not_found(name, namespace_name, version)
|
221
|
+
error_msg = if namespace_name == :default
|
222
|
+
"No task handler for #{name}"
|
223
|
+
else
|
224
|
+
"No task handler for #{name} in namespace #{namespace_name} and version #{version}"
|
225
|
+
end
|
226
|
+
|
227
|
+
log_registry_error('handler_not_found', StandardError.new(error_msg),
|
228
|
+
handler_name: name,
|
229
|
+
namespace_name: namespace_name,
|
230
|
+
version: version)
|
231
|
+
|
232
|
+
raise(Tasker::ProceduralError, error_msg)
|
233
|
+
end
|
234
|
+
|
235
|
+
# Count total handlers across all namespaces and versions
|
236
|
+
#
|
237
|
+
# @return [Integer] Total number of registered handlers
|
238
|
+
def count_total_handlers
|
239
|
+
@handler_classes.values.sum do |namespace_handlers|
|
240
|
+
namespace_handlers.values.sum(&:size)
|
241
|
+
end
|
242
|
+
end
|
243
|
+
|
244
|
+
# Count handlers by namespace
|
245
|
+
#
|
246
|
+
# @return [Hash] Namespace => handler count mapping
|
247
|
+
def count_handlers_by_namespace
|
248
|
+
@handler_classes.transform_values do |namespace_handlers|
|
249
|
+
namespace_handlers.values.sum(&:size)
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
# Count versions by namespace
|
254
|
+
#
|
255
|
+
# @return [Hash] Namespace => version count mapping
|
256
|
+
def count_versions_by_namespace
|
257
|
+
@handler_classes.transform_values do |namespace_handlers|
|
258
|
+
namespace_handlers.keys.size
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Automatically discover and register custom events from step handlers
|
263
|
+
#
|
264
|
+
# @param handler_class [Class, String] The handler class to scan for custom events
|
265
|
+
# @return [void]
|
266
|
+
# @raise [Tasker::ConfigurationError] If custom event configuration fails
|
267
|
+
def discover_and_register_custom_events(handler_class)
|
268
|
+
# Get the actual class object
|
269
|
+
klass = if handler_class.is_a?(Class)
|
270
|
+
handler_class
|
271
|
+
else
|
272
|
+
handler_class.to_s.camelize.constantize
|
273
|
+
end
|
274
|
+
|
275
|
+
# Check if this is a step handler class (has custom_event_configuration method)
|
276
|
+
if klass.respond_to?(:custom_event_configuration)
|
277
|
+
# This is a step handler class - register its custom events directly
|
278
|
+
# Configuration failures should be visible errors, not silent warnings
|
279
|
+
class_events = klass.custom_event_configuration
|
280
|
+
register_custom_events_from_config(class_events, klass)
|
281
|
+
return
|
282
|
+
end
|
283
|
+
|
284
|
+
# Check if this is a task handler class (has step_templates instance method)
|
285
|
+
# We need to avoid instantiating task handler classes as it causes recursion
|
286
|
+
nil unless klass.instance_methods(false).include?(:step_templates)
|
287
|
+
|
288
|
+
# For task handler classes, we'll register custom events from step template definitions
|
289
|
+
# but we can't safely instantiate the class here due to recursion
|
290
|
+
# Instead, we'll let the step handlers register their own events when they're loaded
|
291
|
+
# This is a limitation we accept to avoid the recursive instantiation issue
|
292
|
+
|
293
|
+
# NOTE: YAML-based custom events in step templates will be handled during
|
294
|
+
# the task building process, not here
|
295
|
+
end
|
296
|
+
|
297
|
+
# Register custom events from configuration (either class-based or YAML-based)
|
298
|
+
#
|
299
|
+
# @param events_config [Array<Hash>] Array of event configurations
|
300
|
+
# @param handler_class [Class] The handler class that can fire these events
|
301
|
+
# @return [void]
|
302
|
+
def register_custom_events_from_config(events_config, handler_class)
|
303
|
+
events_config.each do |event_config|
|
304
|
+
# Support both symbol and string keys
|
305
|
+
event_name = event_config[:name] || event_config['name']
|
306
|
+
description = event_config[:description] || event_config['description'] ||
|
307
|
+
"Custom event from #{handler_class.name}"
|
308
|
+
|
309
|
+
next unless event_name
|
310
|
+
|
311
|
+
# Add the handler class to fired_by array automatically
|
312
|
+
fired_by = [handler_class.name]
|
313
|
+
|
314
|
+
Tasker::Events::CustomRegistry.instance.register_event(
|
315
|
+
event_name,
|
316
|
+
description: description,
|
317
|
+
fired_by: fired_by
|
318
|
+
)
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|
322
|
+
end
|
@@ -0,0 +1,186 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'timeout'
|
4
|
+
|
5
|
+
module Tasker
|
6
|
+
module Health
|
7
|
+
# ReadinessChecker validates basic system readiness
|
8
|
+
#
|
9
|
+
# Performs lightweight checks to determine if the system can accept new requests.
|
10
|
+
# Designed for Kubernetes readiness probes with fast response times.
|
11
|
+
#
|
12
|
+
# @example Basic usage
|
13
|
+
# checker = Tasker::Health::ReadinessChecker.new
|
14
|
+
# result = checker.check
|
15
|
+
# puts result[:ready] # true/false
|
16
|
+
#
|
17
|
+
# @example With custom timeout
|
18
|
+
# checker = Tasker::Health::ReadinessChecker.new(timeout: 3.0)
|
19
|
+
# result = checker.check
|
20
|
+
class ReadinessChecker
|
21
|
+
# @return [Float] Timeout for readiness checks in seconds
|
22
|
+
attr_reader :timeout
|
23
|
+
|
24
|
+
# Initialize readiness checker
|
25
|
+
#
|
26
|
+
# @param timeout [Float] Maximum time to wait for checks (default: 5.0 seconds)
|
27
|
+
def initialize(timeout: nil)
|
28
|
+
@timeout = timeout || Tasker.configuration.health.readiness_timeout_seconds
|
29
|
+
end
|
30
|
+
|
31
|
+
# Class method for simple readiness check
|
32
|
+
#
|
33
|
+
# @return [Boolean] Whether system is ready
|
34
|
+
def self.ready?
|
35
|
+
new.check[:ready]
|
36
|
+
end
|
37
|
+
|
38
|
+
# Class method for detailed readiness status
|
39
|
+
#
|
40
|
+
# @return [Hash] Detailed readiness status
|
41
|
+
def self.detailed_status
|
42
|
+
new.check
|
43
|
+
end
|
44
|
+
|
45
|
+
# Perform readiness check
|
46
|
+
#
|
47
|
+
# @return [Hash] Readiness status with details
|
48
|
+
# - :ready [Boolean] Overall readiness status
|
49
|
+
# - :checks [Hash] Individual check results
|
50
|
+
# - :message [String] Status message
|
51
|
+
# - :timestamp [Time] When check was performed
|
52
|
+
def check
|
53
|
+
start_time = Time.current
|
54
|
+
checks = {}
|
55
|
+
|
56
|
+
begin
|
57
|
+
# Use timeout protection for all checks
|
58
|
+
Timeout.timeout(@timeout) do
|
59
|
+
checks[:database] = check_database_connection_with_timing
|
60
|
+
checks[:cache] = check_cache_availability_with_timing
|
61
|
+
end
|
62
|
+
|
63
|
+
ready = checks.values.all? { |check| check[:status] == 'healthy' }
|
64
|
+
failed_checks = checks.select { |_name, check| check[:status] == 'unhealthy' }.keys.map(&:to_s)
|
65
|
+
|
66
|
+
result = {
|
67
|
+
ready: ready,
|
68
|
+
checks: checks,
|
69
|
+
message: ready ? 'System is ready' : 'System is not ready',
|
70
|
+
timestamp: Time.current,
|
71
|
+
check_duration: Time.current - start_time
|
72
|
+
}
|
73
|
+
|
74
|
+
# Add failed_checks if there are any failures
|
75
|
+
result[:failed_checks] = failed_checks unless failed_checks.empty?
|
76
|
+
result
|
77
|
+
rescue Timeout::Error
|
78
|
+
{
|
79
|
+
ready: false,
|
80
|
+
checks: checks,
|
81
|
+
message: "Readiness check timed out after #{@timeout} seconds",
|
82
|
+
timestamp: Time.current,
|
83
|
+
check_duration: Time.current - start_time
|
84
|
+
}
|
85
|
+
rescue StandardError => e
|
86
|
+
{
|
87
|
+
ready: false,
|
88
|
+
checks: checks,
|
89
|
+
message: "Readiness check failed: #{e.message}",
|
90
|
+
error: e.class.name,
|
91
|
+
timestamp: Time.current,
|
92
|
+
check_duration: Time.current - start_time
|
93
|
+
}
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
private
|
98
|
+
|
99
|
+
# Check database connection with timing
|
100
|
+
#
|
101
|
+
# @return [Hash] Database check result with response time
|
102
|
+
def check_database_connection_with_timing
|
103
|
+
start_time = Time.current
|
104
|
+
ActiveRecord::Base.connection.execute('SELECT 1')
|
105
|
+
response_time = ((Time.current - start_time) * 1000).round(2)
|
106
|
+
|
107
|
+
{
|
108
|
+
status: 'healthy',
|
109
|
+
message: 'Database connection active',
|
110
|
+
response_time_ms: response_time
|
111
|
+
}
|
112
|
+
rescue StandardError => e
|
113
|
+
response_time = ((Time.current - start_time) * 1000).round(2)
|
114
|
+
{
|
115
|
+
status: 'unhealthy',
|
116
|
+
message: "Database connection failed: #{e.message}",
|
117
|
+
error: "#{e.class.name}: #{e.message}",
|
118
|
+
response_time_ms: response_time
|
119
|
+
}
|
120
|
+
end
|
121
|
+
|
122
|
+
# Check cache availability with timing and strategy awareness
|
123
|
+
#
|
124
|
+
# Enhanced with cache strategy detection to provide detailed capability information
|
125
|
+
# @return [Hash] Cache check result with response time and strategy details
|
126
|
+
def check_cache_availability_with_timing
|
127
|
+
start_time = Time.current
|
128
|
+
|
129
|
+
# Get cache strategy for enhanced diagnostics
|
130
|
+
cache_strategy = Tasker::CacheStrategy.detect
|
131
|
+
|
132
|
+
# Simple cache test - write and read a test key
|
133
|
+
test_key = "tasker_readiness_check_#{SecureRandom.hex(8)}"
|
134
|
+
test_value = Time.current.to_i
|
135
|
+
|
136
|
+
Rails.cache.write(test_key, test_value, expires_in: 1.minute)
|
137
|
+
cached_value = Rails.cache.read(test_key)
|
138
|
+
Rails.cache.delete(test_key) # cleanup
|
139
|
+
|
140
|
+
response_time = ((Time.current - start_time) * 1000).round(2)
|
141
|
+
|
142
|
+
if cached_value == test_value
|
143
|
+
{
|
144
|
+
status: 'healthy',
|
145
|
+
message: 'Cache is available',
|
146
|
+
response_time_ms: response_time,
|
147
|
+
cache_store: cache_strategy.store_class_name,
|
148
|
+
coordination_strategy: cache_strategy.coordination_mode,
|
149
|
+
distributed: cache_strategy.supports?(:distributed),
|
150
|
+
atomic_operations: cache_strategy.supports?(:atomic_increment),
|
151
|
+
locking_support: cache_strategy.supports?(:locking)
|
152
|
+
}
|
153
|
+
else
|
154
|
+
{
|
155
|
+
status: 'unhealthy',
|
156
|
+
message: 'Cache read/write test failed',
|
157
|
+
error: 'CacheTestFailed',
|
158
|
+
response_time_ms: response_time,
|
159
|
+
cache_store: cache_strategy.store_class_name,
|
160
|
+
coordination_strategy: cache_strategy.coordination_mode
|
161
|
+
}
|
162
|
+
end
|
163
|
+
rescue StandardError => e
|
164
|
+
response_time = ((Time.current - start_time) * 1000).round(2)
|
165
|
+
|
166
|
+
# Try to get cache strategy info even if test failed
|
167
|
+
strategy_info = begin
|
168
|
+
strategy = Tasker::CacheStrategy.detect
|
169
|
+
{
|
170
|
+
cache_store: strategy.store_class_name,
|
171
|
+
coordination_strategy: strategy.coordination_mode
|
172
|
+
}
|
173
|
+
rescue StandardError
|
174
|
+
{ cache_store: 'Unknown', coordination_strategy: 'unknown' }
|
175
|
+
end
|
176
|
+
|
177
|
+
{
|
178
|
+
status: 'unhealthy',
|
179
|
+
message: "Cache check failed: #{e.message}",
|
180
|
+
error: "#{e.class.name}: #{e.message}",
|
181
|
+
response_time_ms: response_time
|
182
|
+
}.merge(strategy_info)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|