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,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# typed: false
|
4
|
+
|
5
|
+
module Tasker
|
6
|
+
class ApplicationController < ActionController::API
|
7
|
+
include Tasker::Concerns::Authenticatable
|
8
|
+
include Tasker::Concerns::ControllerAuthorizable
|
9
|
+
|
10
|
+
# Handle authentication errors with proper HTTP status codes
|
11
|
+
rescue_from Tasker::Authentication::AuthenticationError do |exception|
|
12
|
+
render json: { error: 'Unauthorized', message: exception.message }, status: :unauthorized
|
13
|
+
end
|
14
|
+
|
15
|
+
rescue_from Tasker::Authentication::ConfigurationError do |exception|
|
16
|
+
render json: { error: 'Authentication Configuration Error', message: exception.message },
|
17
|
+
status: :internal_server_error
|
18
|
+
end
|
19
|
+
|
20
|
+
rescue_from Tasker::Authentication::InterfaceError do |exception|
|
21
|
+
render json: { error: 'Authentication Interface Error', message: exception.message },
|
22
|
+
status: :internal_server_error
|
23
|
+
end
|
24
|
+
|
25
|
+
# Handle authorization errors with proper HTTP status codes
|
26
|
+
rescue_from Tasker::Authorization::UnauthorizedError do |exception|
|
27
|
+
render json: { error: 'Forbidden', message: exception.message }, status: :forbidden
|
28
|
+
end
|
29
|
+
|
30
|
+
rescue_from Tasker::Authorization::ConfigurationError do |exception|
|
31
|
+
render json: { error: 'Authorization Configuration Error', message: exception.message },
|
32
|
+
status: :internal_server_error
|
33
|
+
end
|
34
|
+
|
35
|
+
# Handle interface errors where coordinators don't implement required methods
|
36
|
+
rescue_from NoMethodError do |exception|
|
37
|
+
raise exception unless exception.message.include?('authorize!')
|
38
|
+
|
39
|
+
render json: {
|
40
|
+
error: 'Authorization Interface Error',
|
41
|
+
message: 'Coordinator does not implement required authorize! method'
|
42
|
+
}, status: :internal_server_error
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_dependency 'tasker/application_controller'
|
5
|
+
|
6
|
+
module Tasker
|
7
|
+
class GraphqlController < ApplicationController
|
8
|
+
# If accessing from outside this domain, nullify the session
|
9
|
+
# This allows for outside API access while preventing CSRF attacks,
|
10
|
+
# but you'll have to authenticate your user separately
|
11
|
+
# protect_from_forgery with: :null_session
|
12
|
+
|
13
|
+
# Skip the standard controller authorization - we handle GraphQL authorization manually
|
14
|
+
skip_before_action :authorize_tasker_action!, if: :authorization_enabled?
|
15
|
+
|
16
|
+
def execute
|
17
|
+
variables = prepare_variables(params[:variables])
|
18
|
+
query = params[:query]
|
19
|
+
operation_name = params[:operationName]
|
20
|
+
|
21
|
+
# Authorize GraphQL operations before execution
|
22
|
+
authorize_graphql_operations!(query, operation_name) if authorization_enabled?
|
23
|
+
|
24
|
+
context = {
|
25
|
+
# Query context goes here, for example:
|
26
|
+
current_user: current_tasker_user,
|
27
|
+
authenticated: tasker_user_authenticated?
|
28
|
+
}
|
29
|
+
result = Tasker::TaskerRailsSchema.execute(query, variables: variables, context: context,
|
30
|
+
operation_name: operation_name)
|
31
|
+
render(json: result)
|
32
|
+
rescue StandardError => e
|
33
|
+
raise(e) unless Rails.env.development?
|
34
|
+
|
35
|
+
handle_error_in_development(e)
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
# Handle variables in form data, JSON body, or a blank value
|
41
|
+
def prepare_variables(variables_param)
|
42
|
+
case variables_param
|
43
|
+
when String
|
44
|
+
if variables_param.present?
|
45
|
+
JSON.parse(variables_param) || {}
|
46
|
+
else
|
47
|
+
{}
|
48
|
+
end
|
49
|
+
when Hash
|
50
|
+
variables_param
|
51
|
+
when ActionController::Parameters
|
52
|
+
variables_param.to_unsafe_hash # GraphQL-Ruby will validate name and type of incoming variables.
|
53
|
+
when nil
|
54
|
+
{}
|
55
|
+
else
|
56
|
+
raise(ArgumentError, "Unexpected parameter: #{variables_param}")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def handle_error_in_development(error)
|
61
|
+
logger.error(error.message)
|
62
|
+
logger.error(error.backtrace.join("\n"))
|
63
|
+
|
64
|
+
render(json: { errors: [{ message: error.message, backtrace: error.backtrace }], data: {} },
|
65
|
+
status: :internal_server_error)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Authorization methods for GraphQL operations
|
69
|
+
|
70
|
+
def authorization_enabled?
|
71
|
+
Tasker.configuration.auth.authorization_enabled
|
72
|
+
end
|
73
|
+
|
74
|
+
def authorize_graphql_operations!(query_string, operation_name)
|
75
|
+
return if query_string.blank?
|
76
|
+
|
77
|
+
# Parse the GraphQL query to extract operations
|
78
|
+
operations = extract_graphql_operations(query_string, operation_name)
|
79
|
+
|
80
|
+
# Check authorization for each operation
|
81
|
+
operations.each do |operation|
|
82
|
+
resource, action = map_graphql_operation_to_permission(operation)
|
83
|
+
next unless resource && action
|
84
|
+
|
85
|
+
authorization_coordinator.authorize!(resource, action, graphql_authorization_context(operation))
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def extract_graphql_operations(query_string, _operation_name)
|
90
|
+
# Simple regex-based extraction of GraphQL operations for Tasker's current use case.
|
91
|
+
# This approach is sufficient for Tasker's limited, well-defined operations without aliases,
|
92
|
+
# fragments, or complex nesting. Consider upgrading to GraphQL-Ruby's parser if you add:
|
93
|
+
# - Field aliases (e.g., { taskList: tasks { ... } })
|
94
|
+
# - GraphQL fragments (e.g., { ...TaskFields })
|
95
|
+
# - Multiple operations in a single query
|
96
|
+
# - Operations with comments or complex string literals
|
97
|
+
operations = []
|
98
|
+
|
99
|
+
# Clean the query string
|
100
|
+
query_string = query_string.strip
|
101
|
+
|
102
|
+
# Determine if this is a query or mutation
|
103
|
+
field_matches = query_string.scan(/{\s*(\w+)(?:\s*\([^)]*\))?\s*{/)
|
104
|
+
if /^\s*mutation/i.match?(query_string)
|
105
|
+
# Extract mutation fields
|
106
|
+
# Pattern: mutation { mutationName(args) { ... } }
|
107
|
+
field_matches.flatten.each do |field|
|
108
|
+
operations << { type: :mutation, name: field.strip }
|
109
|
+
end
|
110
|
+
else
|
111
|
+
# Default to query - extract query fields
|
112
|
+
# Pattern: query { fieldName(args) { ... } } or { fieldName(args) { ... } }
|
113
|
+
field_matches.flatten.each do |field|
|
114
|
+
operations << { type: :query, name: field.strip }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
# Debug logging
|
119
|
+
Rails.logger.debug { "GraphQL Query: #{query_string}" }
|
120
|
+
Rails.logger.debug { "Extracted Operations: #{operations.inspect}" }
|
121
|
+
|
122
|
+
operations
|
123
|
+
end
|
124
|
+
|
125
|
+
def map_graphql_operation_to_permission(operation)
|
126
|
+
case operation[:type]
|
127
|
+
when :query
|
128
|
+
map_query_to_permission(operation[:name])
|
129
|
+
when :mutation
|
130
|
+
map_mutation_to_permission(operation[:name])
|
131
|
+
else
|
132
|
+
[nil, nil]
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def map_query_to_permission(query_name)
|
137
|
+
case query_name
|
138
|
+
when 'tasks', 'tasksByStatus', 'tasksByAnnotation'
|
139
|
+
['tasker.task', :index]
|
140
|
+
when 'task'
|
141
|
+
['tasker.task', :show]
|
142
|
+
when 'step'
|
143
|
+
['tasker.workflow_step', :show]
|
144
|
+
when 'annotationTypes'
|
145
|
+
# This might be a system-level query that doesn't need authorization
|
146
|
+
[nil, nil]
|
147
|
+
else
|
148
|
+
# Unknown query - deny by default
|
149
|
+
['unknown.resource', :unknown]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
def map_mutation_to_permission(mutation_name)
|
154
|
+
case mutation_name
|
155
|
+
when 'createTask'
|
156
|
+
['tasker.task', :create]
|
157
|
+
when 'updateTask'
|
158
|
+
['tasker.task', :update]
|
159
|
+
when 'cancelTask'
|
160
|
+
['tasker.task', :cancel]
|
161
|
+
when 'updateStep'
|
162
|
+
['tasker.workflow_step', :update]
|
163
|
+
when 'cancelStep'
|
164
|
+
['tasker.workflow_step', :cancel]
|
165
|
+
else
|
166
|
+
# Unknown mutation - deny by default
|
167
|
+
['unknown.resource', :unknown]
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
def authorization_coordinator
|
172
|
+
@authorization_coordinator ||= build_authorization_coordinator
|
173
|
+
end
|
174
|
+
|
175
|
+
def build_authorization_coordinator
|
176
|
+
coordinator_class = Tasker.configuration.auth.authorization_coordinator_class.constantize
|
177
|
+
coordinator_class.new(current_tasker_user)
|
178
|
+
rescue NameError => e
|
179
|
+
coordinator_class_name = Tasker.configuration.auth.authorization_coordinator_class
|
180
|
+
raise Tasker::Authorization::ConfigurationError,
|
181
|
+
"Authorization coordinator class '#{coordinator_class_name}' not found: #{e.message}"
|
182
|
+
end
|
183
|
+
|
184
|
+
def graphql_authorization_context(operation)
|
185
|
+
{
|
186
|
+
controller: self,
|
187
|
+
params: params,
|
188
|
+
graphql_operation: operation,
|
189
|
+
user: current_tasker_user
|
190
|
+
}
|
191
|
+
end
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
# typed: false
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative 'application_controller'
|
5
|
+
|
6
|
+
module Tasker
|
7
|
+
class HandlersController < ApplicationController
|
8
|
+
before_action :set_handler_factory
|
9
|
+
before_action :set_intelligent_cache
|
10
|
+
|
11
|
+
# GET /handlers - List all namespaces with intelligent caching
|
12
|
+
def index
|
13
|
+
cache_key = "tasker:handlers:namespaces:#{handler_registry_version}"
|
14
|
+
|
15
|
+
cached_data = @intelligent_cache.intelligent_fetch(cache_key, base_ttl: 2.minutes) do
|
16
|
+
{
|
17
|
+
namespaces: @handler_factory.registered_namespaces.map do |namespace|
|
18
|
+
{
|
19
|
+
name: namespace.to_s,
|
20
|
+
handler_count: count_handlers_in_namespace(namespace)
|
21
|
+
}
|
22
|
+
end,
|
23
|
+
total_namespaces: @handler_factory.registered_namespaces.size,
|
24
|
+
generated_at: Time.current
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
render json: cached_data, status: :ok
|
29
|
+
end
|
30
|
+
|
31
|
+
# GET /handlers/:namespace - List handlers in a specific namespace
|
32
|
+
def show_namespace
|
33
|
+
namespace_name = params[:namespace]
|
34
|
+
|
35
|
+
unless @handler_factory.registered_namespaces.include?(namespace_name.to_sym)
|
36
|
+
render json: { error: 'Namespace not found' }, status: :not_found
|
37
|
+
return
|
38
|
+
end
|
39
|
+
|
40
|
+
namespace_handlers = @handler_factory.list_handlers(namespace: namespace_name)
|
41
|
+
|
42
|
+
handlers_data = namespace_handlers.map do |handler_name, versions|
|
43
|
+
{
|
44
|
+
name: handler_name,
|
45
|
+
namespace: namespace_name,
|
46
|
+
versions: versions.keys.sort,
|
47
|
+
latest_version: versions.keys.max,
|
48
|
+
handler_count: versions.size
|
49
|
+
}
|
50
|
+
end
|
51
|
+
|
52
|
+
render json: {
|
53
|
+
namespace: namespace_name,
|
54
|
+
handlers: handlers_data,
|
55
|
+
total_handlers: handlers_data.size
|
56
|
+
}, status: :ok
|
57
|
+
end
|
58
|
+
|
59
|
+
# GET /handlers/:namespace/:name - Show specific handler with dependency graph (cached)
|
60
|
+
def show
|
61
|
+
namespace_name = params[:namespace]
|
62
|
+
handler_name = params[:name]
|
63
|
+
version = params[:version] || '0.1.0'
|
64
|
+
|
65
|
+
unless @handler_factory.registered_namespaces.include?(namespace_name.to_sym)
|
66
|
+
render json: { error: 'Namespace not found' }, status: :not_found
|
67
|
+
return
|
68
|
+
end
|
69
|
+
|
70
|
+
# Use intelligent caching for expensive handler discovery and dependency graph building
|
71
|
+
cache_key = "tasker:handlers:show:#{namespace_name}:#{handler_name}:#{version}:#{handler_registry_version}"
|
72
|
+
|
73
|
+
cached_result = @intelligent_cache.intelligent_fetch(cache_key, base_ttl: 2.minutes) do
|
74
|
+
handler_data = find_handler_data(namespace_name, handler_name, version)
|
75
|
+
|
76
|
+
if handler_data
|
77
|
+
# Add dependency graph information (expensive operation)
|
78
|
+
handler_data[:dependency_graph] = build_dependency_graph(handler_data[:step_templates])
|
79
|
+
{
|
80
|
+
handler: handler_data,
|
81
|
+
generated_at: Time.current,
|
82
|
+
cache_key: cache_key
|
83
|
+
}
|
84
|
+
else
|
85
|
+
{
|
86
|
+
error: 'Handler not found in namespace',
|
87
|
+
generated_at: Time.current
|
88
|
+
}
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
if cached_result[:error]
|
93
|
+
render json: { error: cached_result[:error] }, status: :not_found
|
94
|
+
else
|
95
|
+
render json: cached_result, status: :ok
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def set_handler_factory
|
102
|
+
@handler_factory = Tasker::HandlerFactory.instance
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_intelligent_cache
|
106
|
+
@intelligent_cache = Tasker::Telemetry::IntelligentCacheManager.new
|
107
|
+
end
|
108
|
+
|
109
|
+
# Generate cache version based on handler registry state
|
110
|
+
#
|
111
|
+
# @return [String] Cache version that changes when handlers are registered/updated
|
112
|
+
def handler_registry_version
|
113
|
+
# Use handler factory statistics for cache invalidation
|
114
|
+
namespace_count = @handler_factory.registered_namespaces.size
|
115
|
+
total_handlers = @handler_factory.registered_namespaces.sum do |namespace|
|
116
|
+
@handler_factory.list_handlers(namespace: namespace).size
|
117
|
+
end
|
118
|
+
|
119
|
+
"v1:#{namespace_count}:#{total_handlers}"
|
120
|
+
end
|
121
|
+
|
122
|
+
def count_handlers_in_namespace(namespace)
|
123
|
+
namespace_handlers = @handler_factory.list_handlers(namespace: namespace)
|
124
|
+
namespace_handlers.size
|
125
|
+
end
|
126
|
+
|
127
|
+
def find_handler_data(namespace_name, handler_name, version)
|
128
|
+
# Get all versions for this handler in the namespace
|
129
|
+
namespace_handlers = @handler_factory.list_handlers(namespace: namespace_name)
|
130
|
+
handler_versions = namespace_handlers[handler_name.to_sym]
|
131
|
+
|
132
|
+
return nil unless handler_versions
|
133
|
+
|
134
|
+
# Determine the actual version to use
|
135
|
+
actual_version = if version == 'latest'
|
136
|
+
handler_versions.keys.max
|
137
|
+
elsif version == '0.1.0' && !handler_versions.key?('0.1.0')
|
138
|
+
# Fall back to lowest available version if 0.1.0 doesn't exist
|
139
|
+
handler_versions.keys.min
|
140
|
+
else
|
141
|
+
version
|
142
|
+
end
|
143
|
+
|
144
|
+
# Get the handler class for the specific version
|
145
|
+
handler_class = handler_versions[actual_version]
|
146
|
+
return nil unless handler_class
|
147
|
+
|
148
|
+
# Use the HandlerSerializer to get consistent data structure
|
149
|
+
serializer = Tasker::HandlerSerializer.new(
|
150
|
+
handler_class,
|
151
|
+
handler_name: handler_name,
|
152
|
+
namespace: namespace_name,
|
153
|
+
version: actual_version
|
154
|
+
)
|
155
|
+
serializer.serializable_hash
|
156
|
+
end
|
157
|
+
|
158
|
+
def build_dependency_graph(step_templates)
|
159
|
+
return { nodes: [], edges: [] } unless step_templates.is_a?(Array)
|
160
|
+
|
161
|
+
nodes = []
|
162
|
+
edges = []
|
163
|
+
|
164
|
+
step_templates.each do |step|
|
165
|
+
# Add node for this step
|
166
|
+
nodes << {
|
167
|
+
id: step[:name],
|
168
|
+
name: step[:name],
|
169
|
+
type: 'step',
|
170
|
+
handler_class: step[:handler_class],
|
171
|
+
configuration: step[:configuration] || step[:handler_config] || {}
|
172
|
+
}
|
173
|
+
|
174
|
+
# Add edge if this step depends on another
|
175
|
+
next unless step[:depends_on_step]
|
176
|
+
|
177
|
+
edges << {
|
178
|
+
from: step[:depends_on_step],
|
179
|
+
to: step[:name],
|
180
|
+
type: 'dependency'
|
181
|
+
}
|
182
|
+
end
|
183
|
+
|
184
|
+
{
|
185
|
+
nodes: nodes,
|
186
|
+
edges: edges,
|
187
|
+
execution_order: calculate_execution_order(step_templates)
|
188
|
+
}
|
189
|
+
end
|
190
|
+
|
191
|
+
def calculate_execution_order(step_templates)
|
192
|
+
# Simple topological sort to determine execution order
|
193
|
+
steps_by_name = step_templates.index_by { |step| step[:name] }
|
194
|
+
visited = Set.new
|
195
|
+
order = []
|
196
|
+
|
197
|
+
def visit_step(step_name, steps_by_name, visited, order)
|
198
|
+
return if visited.include?(step_name)
|
199
|
+
|
200
|
+
step = steps_by_name[step_name]
|
201
|
+
return unless step
|
202
|
+
|
203
|
+
# Visit dependencies first
|
204
|
+
visit_step(step[:depends_on_step], steps_by_name, visited, order) if step[:depends_on_step]
|
205
|
+
|
206
|
+
visited.add(step_name)
|
207
|
+
order << step_name
|
208
|
+
end
|
209
|
+
|
210
|
+
steps_by_name.each_key do |step_name|
|
211
|
+
visit_step(step_name, steps_by_name, visited, order)
|
212
|
+
end
|
213
|
+
|
214
|
+
order
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,229 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency 'tasker/application_controller'
|
4
|
+
|
5
|
+
module Tasker
|
6
|
+
# Health check controller providing endpoints for system health monitoring.
|
7
|
+
#
|
8
|
+
# This controller provides three health check endpoints:
|
9
|
+
# - `/health/ready` - Readiness check (K8s probes, always unauthenticated)
|
10
|
+
# - `/health/live` - Liveness check (K8s probes, always unauthenticated)
|
11
|
+
# - `/health/status` - Detailed status (uses system_status.read authorization)
|
12
|
+
#
|
13
|
+
# The status endpoint uses the authorization system with the `system_status.read` permission.
|
14
|
+
# If authorization is disabled or no authorization coordinator is configured, access is allowed.
|
15
|
+
# If authorization is enabled, users need the `tasker.system_status:read` permission.
|
16
|
+
class HealthController < ApplicationController
|
17
|
+
# Skip authentication and authorization for K8s probe endpoints
|
18
|
+
skip_before_action :authenticate_tasker_user!, only: %i[ready live]
|
19
|
+
skip_before_action :authorize_tasker_action!, only: %i[ready live]
|
20
|
+
|
21
|
+
# Set cache headers to prevent caching of health data (except detailed status)
|
22
|
+
before_action :set_cache_headers, except: [:status]
|
23
|
+
|
24
|
+
# Initialize intelligent cache for expensive status operations
|
25
|
+
before_action :set_intelligent_cache, only: [:status]
|
26
|
+
|
27
|
+
# Readiness check endpoint for Kubernetes probes
|
28
|
+
# Always returns quickly and doesn't require authentication/authorization
|
29
|
+
#
|
30
|
+
# @return [JSON] Simple ready/not ready status
|
31
|
+
def ready
|
32
|
+
result = Tasker::Health::ReadinessChecker.ready?
|
33
|
+
|
34
|
+
if result[:ready]
|
35
|
+
render json: result, status: :ok
|
36
|
+
else
|
37
|
+
render json: result, status: :service_unavailable
|
38
|
+
end
|
39
|
+
rescue StandardError => e
|
40
|
+
render json: {
|
41
|
+
ready: false,
|
42
|
+
error: 'Health check failed',
|
43
|
+
message: e.message,
|
44
|
+
timestamp: Time.current.iso8601
|
45
|
+
}, status: :service_unavailable
|
46
|
+
end
|
47
|
+
|
48
|
+
# Liveness check endpoint for Kubernetes probes
|
49
|
+
# Always returns 200 OK and doesn't require authentication/authorization
|
50
|
+
#
|
51
|
+
# @return [JSON] Simple alive status
|
52
|
+
def live
|
53
|
+
render json: {
|
54
|
+
alive: true,
|
55
|
+
timestamp: Time.current.iso8601,
|
56
|
+
service: 'tasker'
|
57
|
+
}, status: :ok
|
58
|
+
end
|
59
|
+
|
60
|
+
# Detailed status endpoint with comprehensive system metrics (cached)
|
61
|
+
# Uses system_status.read authorization if authorization is enabled
|
62
|
+
# Results are cached using IntelligentCacheManager for performance
|
63
|
+
#
|
64
|
+
# @return [JSON] Detailed system status and metrics
|
65
|
+
def status
|
66
|
+
# Use intelligent caching for expensive system status analysis
|
67
|
+
cache_key = "tasker:health:detailed_status:#{system_status_cache_version}"
|
68
|
+
|
69
|
+
cached_result = @intelligent_cache.intelligent_fetch(cache_key, base_ttl: 60.seconds) do
|
70
|
+
status_result = Tasker::Health::StatusChecker.status
|
71
|
+
|
72
|
+
# Enhance with additional performance analytics
|
73
|
+
enhanced_result = enhance_status_with_analytics(status_result)
|
74
|
+
|
75
|
+
{
|
76
|
+
**enhanced_result,
|
77
|
+
generated_at: Time.current,
|
78
|
+
cache_info: {
|
79
|
+
cached: true,
|
80
|
+
cache_key: cache_key,
|
81
|
+
ttl_base: '5 minutes'
|
82
|
+
}
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
if cached_result[:healthy]
|
87
|
+
render json: cached_result, status: :ok
|
88
|
+
else
|
89
|
+
render json: cached_result, status: :service_unavailable
|
90
|
+
end
|
91
|
+
rescue StandardError => e
|
92
|
+
render json: {
|
93
|
+
healthy: false,
|
94
|
+
error: 'Status check failed',
|
95
|
+
message: e.message,
|
96
|
+
timestamp: Time.current.iso8601
|
97
|
+
}, status: :service_unavailable
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def set_intelligent_cache
|
103
|
+
@intelligent_cache = Tasker::Telemetry::IntelligentCacheManager.new
|
104
|
+
end
|
105
|
+
|
106
|
+
# Generate cache version based on system state for intelligent cache invalidation
|
107
|
+
#
|
108
|
+
# @return [String] Cache version that changes when system state changes significantly
|
109
|
+
def system_status_cache_version
|
110
|
+
# Use current hour and basic system metrics for cache versioning
|
111
|
+
# This ensures cache invalidation every hour and when major system changes occur
|
112
|
+
current_hour = Time.current.strftime('%Y%m%d%H')
|
113
|
+
|
114
|
+
# Include basic system state indicators using scopes
|
115
|
+
active_tasks = Task.created_since(1.hour.ago).count
|
116
|
+
recent_errors = WorkflowStep.failed_since(1.hour.ago).count
|
117
|
+
|
118
|
+
"v1:#{current_hour}:#{active_tasks}:#{recent_errors}"
|
119
|
+
end
|
120
|
+
|
121
|
+
# Enhance basic status with additional performance analytics
|
122
|
+
#
|
123
|
+
# @param status_result [Hash] Basic status from StatusChecker
|
124
|
+
# @return [Hash] Enhanced status with performance insights
|
125
|
+
def enhance_status_with_analytics(status_result)
|
126
|
+
# Add performance trend analysis
|
127
|
+
performance_trends = calculate_performance_trends
|
128
|
+
|
129
|
+
# Add cache performance metrics
|
130
|
+
cache_performance = @intelligent_cache.export_performance_metrics
|
131
|
+
|
132
|
+
# Enhance the original status with analytics
|
133
|
+
status_result.merge(
|
134
|
+
performance_analytics: {
|
135
|
+
trends: performance_trends,
|
136
|
+
cache_performance: cache_performance,
|
137
|
+
analysis_period: '1 hour',
|
138
|
+
enhanced_at: Time.current
|
139
|
+
}
|
140
|
+
)
|
141
|
+
rescue StandardError => e
|
142
|
+
# If analytics enhancement fails, return original status with error note
|
143
|
+
status_result.merge(
|
144
|
+
performance_analytics: {
|
145
|
+
error: "Analytics enhancement failed: #{e.message}",
|
146
|
+
fallback_mode: true
|
147
|
+
}
|
148
|
+
)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Calculate performance trends for the last hour
|
152
|
+
#
|
153
|
+
# @return [Hash] Performance trend analysis
|
154
|
+
def calculate_performance_trends
|
155
|
+
one_hour_ago = 1.hour.ago
|
156
|
+
|
157
|
+
{
|
158
|
+
task_creation_rate: Task.created_since(one_hour_ago).count,
|
159
|
+
completion_rate: Task.completed_since(one_hour_ago).count,
|
160
|
+
error_rate: Task.failed_since(one_hour_ago).count,
|
161
|
+
avg_step_duration: calculate_average_step_duration(one_hour_ago)
|
162
|
+
}
|
163
|
+
end
|
164
|
+
|
165
|
+
# Calculate average step duration for performance trending
|
166
|
+
#
|
167
|
+
# @param since [Time] Calculate duration since this time
|
168
|
+
# @return [Float] Average duration in seconds
|
169
|
+
def calculate_average_step_duration(since)
|
170
|
+
completed_steps = WorkflowStep.completed_since(since)
|
171
|
+
|
172
|
+
return 0.0 if completed_steps.empty?
|
173
|
+
|
174
|
+
durations = completed_steps.filter_map do |step|
|
175
|
+
next 0.0 unless step.created_at && step.updated_at
|
176
|
+
|
177
|
+
(step.updated_at - step.created_at).to_f
|
178
|
+
end
|
179
|
+
|
180
|
+
durations.empty? ? 0.0 : (durations.sum / durations.size).round(3)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Override the resource name for authorization
|
184
|
+
# Maps status action to health_status resource instead of health resource
|
185
|
+
#
|
186
|
+
# @return [String] The resource name for authorization
|
187
|
+
def tasker_resource_name
|
188
|
+
case action_name
|
189
|
+
when 'status'
|
190
|
+
Tasker::Authorization::ResourceConstants::RESOURCES::HEALTH_STATUS
|
191
|
+
else
|
192
|
+
super
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
# Override the action name for authorization
|
197
|
+
# Maps status action to index action instead of status action
|
198
|
+
#
|
199
|
+
# @return [Symbol] The action name for authorization
|
200
|
+
def tasker_action_name
|
201
|
+
case action_name
|
202
|
+
when 'status'
|
203
|
+
Tasker::Authorization::ResourceConstants::ACTIONS::INDEX
|
204
|
+
else
|
205
|
+
super
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
# Override authentication check for status endpoint
|
210
|
+
# Uses health configuration instead of global auth configuration
|
211
|
+
#
|
212
|
+
# @return [Boolean] True if authentication should be skipped
|
213
|
+
def skip_authentication?
|
214
|
+
case action_name
|
215
|
+
when 'status'
|
216
|
+
!Tasker.configuration.health.status_requires_authentication
|
217
|
+
else
|
218
|
+
super
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Set appropriate cache control headers for health endpoints
|
223
|
+
def set_cache_headers
|
224
|
+
response.headers['Cache-Control'] = 'no-cache, no-store, must-revalidate'
|
225
|
+
response.headers['Pragma'] = 'no-cache'
|
226
|
+
response.headers['Expires'] = '0'
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|