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,107 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators'
|
4
|
+
|
5
|
+
module Tasker
|
6
|
+
module Generators
|
7
|
+
class SubscriberGenerator < Rails::Generators::NamedBase
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
9
|
+
|
10
|
+
desc 'Generate a new Tasker event subscriber'
|
11
|
+
|
12
|
+
class_option :events, type: :array, default: [],
|
13
|
+
desc: 'Events to subscribe to (e.g., task.completed step.failed)'
|
14
|
+
|
15
|
+
class_option :directory, type: :string, default: 'app/subscribers',
|
16
|
+
desc: 'Directory to place the subscriber'
|
17
|
+
|
18
|
+
class_option :metrics, type: :boolean, default: false,
|
19
|
+
desc: 'Generate a specialized metrics collection subscriber'
|
20
|
+
|
21
|
+
def create_subscriber_file
|
22
|
+
if options[:metrics]
|
23
|
+
template 'metrics_subscriber.rb.erb', File.join(options[:directory], "#{file_name}_subscriber.rb")
|
24
|
+
else
|
25
|
+
template 'subscriber.rb.erb', File.join(options[:directory], "#{file_name}_subscriber.rb")
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def create_spec_file
|
30
|
+
return unless defined?(RSpec)
|
31
|
+
|
32
|
+
if options[:metrics]
|
33
|
+
template 'metrics_subscriber_spec.rb.erb', File.join('spec', 'subscribers', "#{file_name}_subscriber_spec.rb")
|
34
|
+
else
|
35
|
+
template 'subscriber_spec.rb.erb', File.join('spec', 'subscribers', "#{file_name}_subscriber_spec.rb")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def show_usage_instructions
|
40
|
+
say "\n#{set_color('Subscriber created successfully!', :green)}"
|
41
|
+
|
42
|
+
if options[:metrics]
|
43
|
+
say "\n#{set_color('Metrics subscriber features:', :cyan)}"
|
44
|
+
say ' - Built-in helper methods for extracting timing, error, and performance metrics'
|
45
|
+
say ' - Automatic tag generation for categorization'
|
46
|
+
say ' - Examples for StatsD, DataDog, Prometheus, and other metrics systems'
|
47
|
+
say ' - Safe numeric value extraction with defaults'
|
48
|
+
end
|
49
|
+
|
50
|
+
say "\nTo register your subscriber, add this to an initializer:"
|
51
|
+
say set_color(" #{class_name}Subscriber.subscribe(Tasker::Events::Publisher.instance)", :cyan)
|
52
|
+
|
53
|
+
if options[:events].any?
|
54
|
+
say "\nYour subscriber will handle these events:"
|
55
|
+
options[:events].each do |event|
|
56
|
+
method_name = "handle_#{event.tr('.', '_')}"
|
57
|
+
say set_color(" #{event} -> #{method_name}", :yellow)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
say "\nAvailable events can be viewed with:"
|
62
|
+
say set_color(' Tasker::Events.catalog.keys', :cyan)
|
63
|
+
|
64
|
+
return unless options[:metrics]
|
65
|
+
|
66
|
+
say "\n#{set_color('Metrics collection examples:', :green)}"
|
67
|
+
say ' - Task completion rates and durations'
|
68
|
+
say ' - Error categorization and retry patterns'
|
69
|
+
say ' - Performance monitoring and resource usage'
|
70
|
+
say ' - Business metrics with proper tagging'
|
71
|
+
end
|
72
|
+
|
73
|
+
private
|
74
|
+
|
75
|
+
def file_name
|
76
|
+
@file_name ||= name.underscore
|
77
|
+
end
|
78
|
+
|
79
|
+
def class_name
|
80
|
+
@class_name ||= name.camelize
|
81
|
+
end
|
82
|
+
|
83
|
+
def subscribed_events
|
84
|
+
if options[:metrics] && options[:events].empty?
|
85
|
+
# Default to common metrics events if none specified
|
86
|
+
%w[task.completed task.failed step.completed step.failed]
|
87
|
+
else
|
88
|
+
options[:events]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def handler_methods
|
93
|
+
subscribed_events.map do |event|
|
94
|
+
{
|
95
|
+
event: event,
|
96
|
+
method_name: "handle_#{event.tr('.', '_')}",
|
97
|
+
method_signature: "handle_#{event.tr('.', '_')}(event)"
|
98
|
+
}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def metrics_type?
|
103
|
+
options[:metrics]
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators'
|
4
|
+
|
5
|
+
module Tasker
|
6
|
+
module Generators
|
7
|
+
class TaskHandlerGenerator < Rails::Generators::NamedBase
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
9
|
+
|
10
|
+
desc 'Generate a new Tasker task handler with TaskNamespace + versioning support, YAML configuration and tests'
|
11
|
+
|
12
|
+
class_option :module_namespace, type: :string, default: nil,
|
13
|
+
desc: 'The module namespace for the task handler ' \
|
14
|
+
'(defaults to Tasker.configuration.engine.default_module_namespace)'
|
15
|
+
class_option :namespace_name, type: :string, default: 'default',
|
16
|
+
desc: 'The TaskNamespace for organizing the task (e.g., payments, inventory, notifications)'
|
17
|
+
class_option :version, type: :string, default: '0.1.0',
|
18
|
+
desc: 'Semantic version for the task handler (e.g., 1.0.0, 2.1.0)'
|
19
|
+
class_option :description, type: :string, default: nil,
|
20
|
+
desc: 'Description of what this task handler does'
|
21
|
+
class_option :steps, type: :array, default: [],
|
22
|
+
desc: 'Step names to include in the task (e.g., --steps=validate,process,complete)'
|
23
|
+
|
24
|
+
def create_task_handler_files
|
25
|
+
# Set variables first
|
26
|
+
@module_namespace = options[:module_namespace] || Tasker.configuration.engine.default_module_namespace
|
27
|
+
@module_path = @module_namespace&.underscore
|
28
|
+
@task_handler_class = name.camelize
|
29
|
+
@task_name = name.underscore
|
30
|
+
@namespace_name = options[:namespace_name]
|
31
|
+
@version = options[:version]
|
32
|
+
@description = options[:description]
|
33
|
+
@steps = options[:steps]
|
34
|
+
|
35
|
+
# Load configuration
|
36
|
+
ensure_configuration_loaded
|
37
|
+
|
38
|
+
# Get directory paths from configuration
|
39
|
+
@task_handler_directory = Tasker.configuration.engine.task_handler_directory
|
40
|
+
@task_config_directory = Tasker.configuration.engine.task_config_directory
|
41
|
+
|
42
|
+
# Ensure directories exist
|
43
|
+
ensure_directories_exist(
|
44
|
+
[
|
45
|
+
task_handler_directory_with_module_path,
|
46
|
+
spec_directory_with_module_path,
|
47
|
+
task_config_directory_with_module_path
|
48
|
+
]
|
49
|
+
)
|
50
|
+
|
51
|
+
# Create the YAML config file
|
52
|
+
template 'task_config.yaml.erb', "#{task_config_directory_with_module_path}/#{@task_name}.yaml"
|
53
|
+
|
54
|
+
# Create the task handler class
|
55
|
+
template 'task_handler.rb.erb', "#{task_handler_directory_with_module_path}/#{@task_name}.rb"
|
56
|
+
|
57
|
+
# Create the task handler spec
|
58
|
+
template 'task_handler_spec.rb.erb', "#{spec_directory_with_module_path}/#{@task_name}_spec.rb"
|
59
|
+
|
60
|
+
display_success_message
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def usable_module_path
|
66
|
+
@module_path ? "#{@module_path}/" : ''
|
67
|
+
end
|
68
|
+
|
69
|
+
def task_handler_directory_with_module_path
|
70
|
+
Rails.root.join("app/#{@task_handler_directory}/#{usable_module_path}")
|
71
|
+
end
|
72
|
+
|
73
|
+
def task_config_directory_with_module_path
|
74
|
+
Rails.root.join("config/#{@task_config_directory}/#{usable_module_path}")
|
75
|
+
end
|
76
|
+
|
77
|
+
def spec_directory_with_module_path
|
78
|
+
Rails.root.join("spec/#{@task_handler_directory}/#{usable_module_path}")
|
79
|
+
end
|
80
|
+
|
81
|
+
def ensure_configuration_loaded
|
82
|
+
# Check if Tasker is already loaded
|
83
|
+
return if defined?(Tasker) && Tasker.respond_to?(:configuration)
|
84
|
+
|
85
|
+
initializer_path = Rails.root.join('config/initializers/tasker.rb')
|
86
|
+
|
87
|
+
# Copy initializer if it doesn't exist
|
88
|
+
unless File.exist?(initializer_path)
|
89
|
+
template_path = File.expand_path('templates/initialize.rb.erb', __dir__)
|
90
|
+
FileUtils.cp(template_path, initializer_path)
|
91
|
+
Rails.logger.debug { "Created Tasker configuration at #{initializer_path}" }
|
92
|
+
end
|
93
|
+
|
94
|
+
# Load the initializer
|
95
|
+
require initializer_path
|
96
|
+
end
|
97
|
+
|
98
|
+
def ensure_directories_exist(dirs)
|
99
|
+
dirs.each do |dir|
|
100
|
+
unless File.directory?(dir)
|
101
|
+
FileUtils.mkdir_p(dir)
|
102
|
+
Rails.logger.debug { "Created directory: #{dir}" }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
def display_success_message
|
108
|
+
say "\nTask handler created successfully!"
|
109
|
+
say ''
|
110
|
+
say 'Files created:'
|
111
|
+
say " - #{task_handler_directory_with_module_path}/#{@task_name}.rb"
|
112
|
+
say " - #{task_config_directory_with_module_path}/#{@task_name}.yaml"
|
113
|
+
say " - #{spec_directory_with_module_path}/#{@task_name}_spec.rb"
|
114
|
+
say ''
|
115
|
+
say 'Next steps:'
|
116
|
+
say ' 1. Define your step handlers in the YAML configuration'
|
117
|
+
say ' 2. Implement step handlers as needed'
|
118
|
+
test_path = "spec/#{@task_handler_directory}/#{usable_module_path}#{@task_name}_spec.rb"
|
119
|
+
say " 3. Run your tests: bundle exec rspec #{test_path}"
|
120
|
+
say ''
|
121
|
+
say 'Usage example:'
|
122
|
+
say ' task_request = Tasker::Types::TaskRequest.new('
|
123
|
+
say " name: '#{@task_name}',"
|
124
|
+
say " namespace: '#{@namespace_name}',"
|
125
|
+
say " version: '#{@version}',"
|
126
|
+
say ' context: { /* your task context */ }'
|
127
|
+
say ' )'
|
128
|
+
say ''
|
129
|
+
say ' handler = Tasker::HandlerFactory.instance.get('
|
130
|
+
say " '#{@task_name}',"
|
131
|
+
say " namespace_name: '#{@namespace_name}',"
|
132
|
+
say " version: '#{@version}'"
|
133
|
+
say ' )'
|
134
|
+
say ' task = handler.initialize_task!(task_request)'
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# API Token authenticator for <%= class_name %>
|
4
|
+
# Generated by: rails generate tasker:authenticator <%= file_name %> --type=api_token
|
5
|
+
#
|
6
|
+
# This authenticator implements API token-based authentication.
|
7
|
+
# Expects tokens to be passed in request headers and looks up users by token.
|
8
|
+
#
|
9
|
+
# Configuration example:
|
10
|
+
# Tasker.configuration do |config|
|
11
|
+
# config.auth do |auth|
|
12
|
+
# auth.strategy = :custom
|
13
|
+
# auth.options = {
|
14
|
+
# authenticator_class: '<%= class_name %>Authenticator',
|
15
|
+
# header_name: 'X-API-Token',
|
16
|
+
# user_class: '<%= user_model_class %>',
|
17
|
+
# token_field: 'api_token'
|
18
|
+
# }
|
19
|
+
# end
|
20
|
+
# end
|
21
|
+
|
22
|
+
class <%= class_name %>Authenticator
|
23
|
+
include Tasker::Authentication::Interface
|
24
|
+
|
25
|
+
def initialize(options = {})
|
26
|
+
@header_name = options[:header_name] || 'X-API-Token'
|
27
|
+
@user_class = options[:user_class] || '<%= user_model_class %>'
|
28
|
+
@token_field = options[:token_field] || 'api_token'
|
29
|
+
@options = options
|
30
|
+
end
|
31
|
+
|
32
|
+
# Required: Authenticate the request, raise exception if fails
|
33
|
+
def authenticate!(controller)
|
34
|
+
user = current_user(controller)
|
35
|
+
unless user
|
36
|
+
raise Tasker::Authentication::AuthenticationError,
|
37
|
+
'Invalid or missing API token'
|
38
|
+
end
|
39
|
+
true
|
40
|
+
end
|
41
|
+
|
42
|
+
# Required: Get the current authenticated user
|
43
|
+
def current_user(controller)
|
44
|
+
return @current_user if defined?(@current_user)
|
45
|
+
|
46
|
+
@current_user = begin
|
47
|
+
token = extract_token(controller.request)
|
48
|
+
return nil unless token
|
49
|
+
|
50
|
+
find_user_by_token(token)
|
51
|
+
rescue StandardError => e
|
52
|
+
Rails.logger.debug "API token authentication failed: #{e.message}"
|
53
|
+
nil
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# Optional: Configuration validation
|
58
|
+
def validate_configuration(options = {})
|
59
|
+
errors = []
|
60
|
+
|
61
|
+
# Validate user class
|
62
|
+
user_class = options[:user_class] || '<%= user_model_class %>'
|
63
|
+
begin
|
64
|
+
model = user_class.constantize
|
65
|
+
|
66
|
+
# Check if the token field exists
|
67
|
+
token_field = options[:token_field] || 'api_token'
|
68
|
+
unless model.column_names.include?(token_field.to_s)
|
69
|
+
errors << "User model '#{user_class}' does not have '#{token_field}' column"
|
70
|
+
end
|
71
|
+
rescue NameError
|
72
|
+
errors << "User class '#{user_class}' not found"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Validate header name
|
76
|
+
header_name = options[:header_name]
|
77
|
+
if header_name.present? && !header_name.is_a?(String)
|
78
|
+
errors << 'Header name must be a string'
|
79
|
+
end
|
80
|
+
|
81
|
+
errors
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
attr_reader :header_name, :user_class, :token_field, :options
|
87
|
+
|
88
|
+
def extract_token(request)
|
89
|
+
# Try configured header first
|
90
|
+
token = request.headers[@header_name]
|
91
|
+
return token if token.present?
|
92
|
+
|
93
|
+
# Fallback to Authorization header with Bearer format
|
94
|
+
auth_header = request.headers['Authorization']
|
95
|
+
return nil unless auth_header.present?
|
96
|
+
|
97
|
+
# Support "Bearer <token>" format
|
98
|
+
auth_header.start_with?('Bearer ') ? auth_header.sub(/^Bearer /, '') : auth_header
|
99
|
+
end
|
100
|
+
|
101
|
+
def find_user_by_token(token)
|
102
|
+
return nil if token.blank?
|
103
|
+
|
104
|
+
user_model = @user_class.constantize
|
105
|
+
user_model.find_by(@token_field => token)
|
106
|
+
rescue ActiveRecord::RecordNotFound, NoMethodError
|
107
|
+
nil
|
108
|
+
end
|
109
|
+
|
110
|
+
def user_model
|
111
|
+
@user_model ||= @user_class.constantize
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
RSpec.describe <%= class_name %>Authenticator, type: :model do
|
6
|
+
let(:options) do
|
7
|
+
{
|
8
|
+
header_name: 'X-API-Token',
|
9
|
+
user_class: '<%= user_model_class %>',
|
10
|
+
token_field: 'api_token'
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:authenticator) { described_class.new(options) }
|
15
|
+
let(:controller) { instance_double('ActionController::Base') }
|
16
|
+
let(:request) { instance_double('ActionDispatch::Request') }
|
17
|
+
let(:headers) { {} }
|
18
|
+
|
19
|
+
before do
|
20
|
+
allow(controller).to receive(:request).and_return(request)
|
21
|
+
allow(request).to receive(:headers).and_return(headers)
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '#initialize' do
|
25
|
+
it 'sets configuration options' do
|
26
|
+
expect(authenticator.send(:header_name)).to eq('X-API-Token')
|
27
|
+
expect(authenticator.send(:user_class)).to eq('<%= user_model_class %>')
|
28
|
+
expect(authenticator.send(:token_field)).to eq('api_token')
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'uses default values when options are not provided' do
|
32
|
+
authenticator = described_class.new
|
33
|
+
expect(authenticator.send(:header_name)).to eq('X-API-Token')
|
34
|
+
expect(authenticator.send(:user_class)).to eq('<%= user_model_class %>')
|
35
|
+
expect(authenticator.send(:token_field)).to eq('api_token')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#current_user' do
|
40
|
+
let(:token) { 'abc123token' }
|
41
|
+
let(:user) { double('User', id: 1) }
|
42
|
+
|
43
|
+
before do
|
44
|
+
# Mock the user model
|
45
|
+
user_model = double('UserModel')
|
46
|
+
allow('<%= user_model_class %>').to receive(:constantize).and_return(user_model)
|
47
|
+
allow(user_model).to receive(:find_by).with('api_token' => token).and_return(user)
|
48
|
+
end
|
49
|
+
|
50
|
+
context 'with valid token in configured header' do
|
51
|
+
before do
|
52
|
+
headers['X-API-Token'] = token
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'returns the authenticated user' do
|
56
|
+
expect(authenticator.current_user(controller)).to eq(user)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context 'with valid token in Authorization header (Bearer format)' do
|
61
|
+
before do
|
62
|
+
headers['Authorization'] = "Bearer #{token}"
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'returns the authenticated user' do
|
66
|
+
expect(authenticator.current_user(controller)).to eq(user)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'with valid token in Authorization header (raw format)' do
|
71
|
+
before do
|
72
|
+
headers['Authorization'] = token
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'returns the authenticated user' do
|
76
|
+
expect(authenticator.current_user(controller)).to eq(user)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'with missing token' do
|
81
|
+
it 'returns nil' do
|
82
|
+
expect(authenticator.current_user(controller)).to be_nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'with invalid token' do
|
87
|
+
before do
|
88
|
+
headers['X-API-Token'] = 'invalid_token'
|
89
|
+
user_model = double('UserModel')
|
90
|
+
allow('<%= user_model_class %>').to receive(:constantize).and_return(user_model)
|
91
|
+
allow(user_model).to receive(:find_by).with('api_token' => 'invalid_token').and_return(nil)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'returns nil' do
|
95
|
+
expect(authenticator.current_user(controller)).to be_nil
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#validate_configuration' do
|
101
|
+
context 'with valid configuration' do
|
102
|
+
before do
|
103
|
+
# Mock valid user model with token field
|
104
|
+
user_model = double('UserModel', column_names: ['id', 'name', 'api_token'])
|
105
|
+
allow('<%= user_model_class %>').to receive(:constantize).and_return(user_model)
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'returns no errors' do
|
109
|
+
errors = authenticator.validate_configuration(options)
|
110
|
+
expect(errors).to be_empty
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
context 'with invalid user class' do
|
115
|
+
let(:invalid_options) { options.merge(user_class: 'NonExistentUser') }
|
116
|
+
|
117
|
+
it 'returns validation error' do
|
118
|
+
errors = authenticator.validate_configuration(invalid_options)
|
119
|
+
expect(errors).to include(/not found/)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'when user model is missing token field' do
|
124
|
+
before do
|
125
|
+
user_model = double('UserModel', column_names: ['id', 'name'])
|
126
|
+
allow('<%= user_model_class %>').to receive(:constantize).and_return(user_model)
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'returns validation error' do
|
130
|
+
errors = authenticator.validate_configuration(options)
|
131
|
+
expect(errors).to include(/does not have 'api_token' column/)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'with invalid header name type' do
|
136
|
+
let(:invalid_options) { options.merge(header_name: 123) }
|
137
|
+
|
138
|
+
it 'returns validation error' do
|
139
|
+
errors = authenticator.validate_configuration(invalid_options)
|
140
|
+
expect(errors).to include('Header name must be a string')
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,95 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Authorization coordinator for <%= @coordinator_class_name %>
|
4
|
+
#
|
5
|
+
# This coordinator provides authorization logic for Tasker resources.
|
6
|
+
# Customize the authorization methods below to implement your business logic.
|
7
|
+
#
|
8
|
+
# For more advanced examples, see:
|
9
|
+
# - docs/AUTH.md (Authorization System section)
|
10
|
+
# - spec/examples/custom_authorization_coordinator.rb
|
11
|
+
# - spec/lib/tasker/authorization/ (test examples)
|
12
|
+
#
|
13
|
+
class <%= @coordinator_class_name %> < Tasker::Authorization::BaseCoordinator
|
14
|
+
protected
|
15
|
+
|
16
|
+
# Implement your authorization logic here
|
17
|
+
#
|
18
|
+
# @param resource [String] The resource being accessed (e.g., 'tasker.task')
|
19
|
+
# @param action [Symbol] The action being performed (e.g., :show, :create)
|
20
|
+
# @param context [Hash] Additional context (controller, params, user, etc.)
|
21
|
+
# @return [Boolean] true if authorized, false otherwise
|
22
|
+
def authorized?(resource, action, context = {})
|
23
|
+
# Return false if no user or user doesn't have permission methods
|
24
|
+
return false unless user&.respond_to?(:has_tasker_permission?)
|
25
|
+
|
26
|
+
case resource
|
27
|
+
when Tasker::Authorization::ResourceConstants::RESOURCES::TASK
|
28
|
+
authorize_task(action, context)
|
29
|
+
when Tasker::Authorization::ResourceConstants::RESOURCES::WORKFLOW_STEP
|
30
|
+
authorize_workflow_step(action, context)
|
31
|
+
when Tasker::Authorization::ResourceConstants::RESOURCES::TASK_DIAGRAM
|
32
|
+
authorize_task_diagram(action, context)
|
33
|
+
when Tasker::Authorization::ResourceConstants::RESOURCES::HEALTH_STATUS
|
34
|
+
authorize_system_status(action, context)
|
35
|
+
else
|
36
|
+
# Deny access to unknown resources
|
37
|
+
false
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# Authorize task operations
|
44
|
+
def authorize_task(action, context)
|
45
|
+
case action
|
46
|
+
when :index, :show
|
47
|
+
# TODO: Implement your read permission logic
|
48
|
+
user.has_tasker_permission?("tasker.task:#{action}")
|
49
|
+
when :create, :update, :destroy, :retry, :cancel
|
50
|
+
# TODO: Implement your write permission logic
|
51
|
+
# Example: Admin users or users with specific permissions
|
52
|
+
user.tasker_admin? || user.has_tasker_permission?("tasker.task:#{action}")
|
53
|
+
else
|
54
|
+
false
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Authorize workflow step operations
|
59
|
+
def authorize_workflow_step(action, context)
|
60
|
+
case action
|
61
|
+
when :index, :show
|
62
|
+
# TODO: Implement your step read logic
|
63
|
+
user.has_tasker_permission?("tasker.workflow_step:#{action}")
|
64
|
+
when :update, :destroy, :retry, :cancel
|
65
|
+
# TODO: Implement your step write logic
|
66
|
+
# Example: Only admins can modify steps
|
67
|
+
user.tasker_admin?
|
68
|
+
else
|
69
|
+
false
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Authorize task diagram operations
|
74
|
+
def authorize_task_diagram(action, context)
|
75
|
+
case action
|
76
|
+
when :index, :show
|
77
|
+
# TODO: Implement your diagram access logic
|
78
|
+
user.has_tasker_permission?("tasker.task_diagram:#{action}")
|
79
|
+
else
|
80
|
+
false
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Authorize system status operations
|
85
|
+
def authorize_system_status(action, context)
|
86
|
+
case action
|
87
|
+
when :read
|
88
|
+
# TODO: Implement your system status access logic
|
89
|
+
# Example: Admin users or users with explicit permission
|
90
|
+
user.tasker_admin? || user.has_tasker_permission?("tasker.system_status:#{action}")
|
91
|
+
else
|
92
|
+
false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|