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,142 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails_helper'
|
4
|
+
|
5
|
+
RSpec.describe <%= @coordinator_class_name %>, type: :model do
|
6
|
+
let(:user_class) { Struct.new(:id, :permissions, :roles, :admin, keyword_init: true) }
|
7
|
+
|
8
|
+
let(:admin_user) do
|
9
|
+
user_class.new(
|
10
|
+
id: 1,
|
11
|
+
permissions: [],
|
12
|
+
roles: ['admin'],
|
13
|
+
admin: true
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:regular_user) do
|
18
|
+
user_class.new(
|
19
|
+
id: 2,
|
20
|
+
permissions: [
|
21
|
+
'tasker.task:index',
|
22
|
+
'tasker.task:show',
|
23
|
+
'tasker.workflow_step:index',
|
24
|
+
'tasker.task_diagram:index'
|
25
|
+
],
|
26
|
+
roles: ['user'],
|
27
|
+
admin: false
|
28
|
+
)
|
29
|
+
end
|
30
|
+
|
31
|
+
let(:coordinator) { described_class.new(user) }
|
32
|
+
|
33
|
+
# Add required methods to test users
|
34
|
+
before do
|
35
|
+
user_class.class_eval do
|
36
|
+
def has_tasker_permission?(permission)
|
37
|
+
permissions.include?(permission)
|
38
|
+
end
|
39
|
+
|
40
|
+
def tasker_admin?
|
41
|
+
admin == true
|
42
|
+
end
|
43
|
+
|
44
|
+
def tasker_roles
|
45
|
+
roles
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe '#authorize!' do
|
51
|
+
context 'with admin user' do
|
52
|
+
let(:user) { admin_user }
|
53
|
+
|
54
|
+
it 'allows admin access to all resources' do
|
55
|
+
expect { coordinator.authorize!('tasker.task', :index) }.not_to raise_error
|
56
|
+
expect { coordinator.authorize!('tasker.task', :create) }.not_to raise_error
|
57
|
+
expect { coordinator.authorize!('tasker.workflow_step', :update) }.not_to raise_error
|
58
|
+
expect { coordinator.authorize!('tasker.task_diagram', :show) }.not_to raise_error
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with regular user' do
|
63
|
+
let(:user) { regular_user }
|
64
|
+
|
65
|
+
it 'allows access to permitted resources' do
|
66
|
+
expect { coordinator.authorize!('tasker.task', :index) }.not_to raise_error
|
67
|
+
expect { coordinator.authorize!('tasker.task', :show) }.not_to raise_error
|
68
|
+
expect { coordinator.authorize!('tasker.workflow_step', :index) }.not_to raise_error
|
69
|
+
expect { coordinator.authorize!('tasker.task_diagram', :index) }.not_to raise_error
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'denies access to forbidden resources' do
|
73
|
+
expect { coordinator.authorize!('tasker.task', :create) }.to raise_error(Tasker::Authorization::UnauthorizedError)
|
74
|
+
expect { coordinator.authorize!('tasker.task', :destroy) }.to raise_error(Tasker::Authorization::UnauthorizedError)
|
75
|
+
expect { coordinator.authorize!('tasker.workflow_step', :update) }.to raise_error(Tasker::Authorization::UnauthorizedError)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'with no user' do
|
80
|
+
let(:user) { nil }
|
81
|
+
|
82
|
+
it 'denies all operations' do
|
83
|
+
expect { coordinator.authorize!('tasker.task', :index) }.to raise_error(Tasker::Authorization::UnauthorizedError)
|
84
|
+
expect { coordinator.authorize!('tasker.workflow_step', :show) }.to raise_error(Tasker::Authorization::UnauthorizedError)
|
85
|
+
expect { coordinator.authorize!('tasker.task_diagram', :show) }.to raise_error(Tasker::Authorization::UnauthorizedError)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#can?' do
|
91
|
+
context 'with admin user' do
|
92
|
+
let(:user) { admin_user }
|
93
|
+
|
94
|
+
it 'returns true for valid operations' do
|
95
|
+
expect(coordinator.can?('tasker.task', :index)).to be true
|
96
|
+
expect(coordinator.can?('tasker.task', :create)).to be true
|
97
|
+
expect(coordinator.can?('tasker.workflow_step', :update)).to be true
|
98
|
+
expect(coordinator.can?('tasker.task_diagram', :show)).to be true
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'with regular user' do
|
103
|
+
let(:user) { regular_user }
|
104
|
+
|
105
|
+
it 'returns true for permitted operations' do
|
106
|
+
expect(coordinator.can?('tasker.task', :index)).to be true
|
107
|
+
expect(coordinator.can?('tasker.task', :show)).to be true
|
108
|
+
expect(coordinator.can?('tasker.workflow_step', :index)).to be true
|
109
|
+
expect(coordinator.can?('tasker.task_diagram', :index)).to be true
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'returns false for forbidden operations' do
|
113
|
+
expect(coordinator.can?('tasker.task', :create)).to be false
|
114
|
+
expect(coordinator.can?('tasker.task', :destroy)).to be false
|
115
|
+
expect(coordinator.can?('tasker.workflow_step', :update)).to be false
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'returns false for unknown resources' do
|
120
|
+
expect(coordinator.can?('unknown.resource', :index)).to be false
|
121
|
+
end
|
122
|
+
|
123
|
+
it 'returns false for unknown actions' do
|
124
|
+
expect(coordinator.can?('tasker.task', :unknown_action)).to be false
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'interface compliance' do
|
129
|
+
it 'inherits from BaseCoordinator' do
|
130
|
+
expect(described_class.superclass).to eq(Tasker::Authorization::BaseCoordinator)
|
131
|
+
end
|
132
|
+
|
133
|
+
it 'implements the required authorized? method' do
|
134
|
+
expect(coordinator).to respond_to(:authorized?, true)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'provides access to the user' do
|
138
|
+
coordinator = described_class.new(regular_user)
|
139
|
+
expect(coordinator.send(:user)).to eq(regular_user)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Custom authenticator for <%= class_name %>
|
4
|
+
# Generated by: rails generate tasker:authenticator <%= file_name %> --type=custom
|
5
|
+
#
|
6
|
+
# This authenticator template provides a starting point for implementing
|
7
|
+
# custom authentication logic in your Tasker application.
|
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
|
+
# user_class: '<%= user_model_class %>'
|
16
|
+
# # Add your custom options here
|
17
|
+
# }
|
18
|
+
# end
|
19
|
+
# end
|
20
|
+
|
21
|
+
class <%= class_name %>Authenticator
|
22
|
+
include Tasker::Authentication::Interface
|
23
|
+
|
24
|
+
def initialize(options = {})
|
25
|
+
@user_class = options[:user_class] || '<%= user_model_class %>'
|
26
|
+
@options = options
|
27
|
+
end
|
28
|
+
|
29
|
+
# Required: Authenticate the request, raise exception if fails
|
30
|
+
def authenticate!(controller)
|
31
|
+
user = current_user(controller)
|
32
|
+
unless user
|
33
|
+
raise Tasker::Authentication::AuthenticationError,
|
34
|
+
'Authentication failed. Please provide valid credentials.'
|
35
|
+
end
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
39
|
+
# Required: Get the current authenticated user
|
40
|
+
def current_user(controller)
|
41
|
+
return @current_user if defined?(@current_user)
|
42
|
+
|
43
|
+
@current_user = begin
|
44
|
+
# TODO: Implement your user lookup logic here
|
45
|
+
# Examples:
|
46
|
+
# - Check session for user ID
|
47
|
+
# - Extract token from headers
|
48
|
+
# - Use existing Rails authentication
|
49
|
+
# - Custom authentication scheme
|
50
|
+
|
51
|
+
# Example session-based lookup:
|
52
|
+
# user_id = controller.session[:user_id]
|
53
|
+
# return nil unless user_id
|
54
|
+
# user_model.find_by(id: user_id)
|
55
|
+
|
56
|
+
# Example header-based lookup:
|
57
|
+
# token = controller.request.headers['Authorization']
|
58
|
+
# return nil unless token
|
59
|
+
# find_user_by_token(token)
|
60
|
+
|
61
|
+
# Placeholder - replace with your logic
|
62
|
+
nil
|
63
|
+
rescue StandardError => e
|
64
|
+
Rails.logger.error "Authentication error in <%= class_name %>Authenticator: #{e.message}"
|
65
|
+
nil
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Optional: Check if user is authenticated (uses current_user by default)
|
70
|
+
def authenticated?(controller)
|
71
|
+
current_user(controller).present?
|
72
|
+
end
|
73
|
+
|
74
|
+
# Optional: Configuration validation
|
75
|
+
def validate_configuration(options = {})
|
76
|
+
errors = []
|
77
|
+
|
78
|
+
# Validate user class
|
79
|
+
user_class = options[:user_class] || '<%= user_model_class %>'
|
80
|
+
begin
|
81
|
+
user_class.constantize
|
82
|
+
rescue NameError
|
83
|
+
errors << "User class '#{user_class}' not found"
|
84
|
+
end
|
85
|
+
|
86
|
+
# TODO: Add your custom validation logic here
|
87
|
+
# Examples:
|
88
|
+
# - Required configuration options
|
89
|
+
# - External service dependencies
|
90
|
+
# - Security settings validation
|
91
|
+
|
92
|
+
errors
|
93
|
+
end
|
94
|
+
|
95
|
+
private
|
96
|
+
|
97
|
+
attr_reader :options, :user_class
|
98
|
+
|
99
|
+
def user_model
|
100
|
+
@user_model ||= @user_class.constantize
|
101
|
+
end
|
102
|
+
|
103
|
+
# TODO: Add your private helper methods here
|
104
|
+
# Examples:
|
105
|
+
# def extract_token(request)
|
106
|
+
# def find_user_by_token(token)
|
107
|
+
# def validate_credentials(credentials)
|
108
|
+
end
|
@@ -0,0 +1,162 @@
|
|
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
|
+
user_class: '<%= user_model_class %>'
|
9
|
+
# Add your custom options here
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:authenticator) { described_class.new(options) }
|
14
|
+
let(:controller) { instance_double('ActionController::Base') }
|
15
|
+
let(:request) { instance_double('ActionDispatch::Request') }
|
16
|
+
let(:headers) { {} }
|
17
|
+
|
18
|
+
before do
|
19
|
+
allow(controller).to receive(:request).and_return(request)
|
20
|
+
allow(request).to receive(:headers).and_return(headers)
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#initialize' do
|
24
|
+
it 'sets default options' do
|
25
|
+
authenticator = described_class.new
|
26
|
+
expect(authenticator.send(:user_class)).to eq('<%= user_model_class %>')
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'accepts custom options' do
|
30
|
+
custom_options = { user_class: 'CustomUser' }
|
31
|
+
authenticator = described_class.new(custom_options)
|
32
|
+
expect(authenticator.send(:user_class)).to eq('CustomUser')
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe '#authenticate!' do
|
37
|
+
context 'when user is authenticated' do
|
38
|
+
before do
|
39
|
+
allow(authenticator).to receive(:current_user).with(controller).and_return(double('User'))
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'returns true' do
|
43
|
+
expect(authenticator.authenticate!(controller)).to be_truthy
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
context 'when user is not authenticated' do
|
48
|
+
before do
|
49
|
+
allow(authenticator).to receive(:current_user).with(controller).and_return(nil)
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'raises AuthenticationError' do
|
53
|
+
expect do
|
54
|
+
authenticator.authenticate!(controller)
|
55
|
+
end.to raise_error(Tasker::Authentication::AuthenticationError)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#current_user' do
|
61
|
+
context 'when user authentication succeeds' do
|
62
|
+
# TODO: Implement test cases based on your authentication logic
|
63
|
+
# Example:
|
64
|
+
# let(:user) { create(:user) }
|
65
|
+
#
|
66
|
+
# before do
|
67
|
+
# # Set up your authentication scenario
|
68
|
+
# # e.g., session, headers, tokens, etc.
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
# it 'returns the authenticated user' do
|
72
|
+
# expect(authenticator.current_user(controller)).to eq(user)
|
73
|
+
# end
|
74
|
+
|
75
|
+
it 'needs implementation based on your authentication logic' do
|
76
|
+
pending 'Implement based on your specific authentication method'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context 'when user authentication fails' do
|
81
|
+
it 'returns nil' do
|
82
|
+
expect(authenticator.current_user(controller)).to be_nil
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when authentication raises an error' do
|
87
|
+
before do
|
88
|
+
# Simulate an error in your authentication logic
|
89
|
+
allow(controller).to receive(:session).and_raise(StandardError, 'Session error')
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns nil and logs the error' do
|
93
|
+
expect(Rails.logger).to receive(:error).with(/Authentication error/)
|
94
|
+
expect(authenticator.current_user(controller)).to be_nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe '#authenticated?' do
|
100
|
+
context 'when current_user returns a user' do
|
101
|
+
before do
|
102
|
+
allow(authenticator).to receive(:current_user).with(controller).and_return(double('User'))
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns true' do
|
106
|
+
expect(authenticator.authenticated?(controller)).to be true
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
context 'when current_user returns nil' do
|
111
|
+
before do
|
112
|
+
allow(authenticator).to receive(:current_user).with(controller).and_return(nil)
|
113
|
+
end
|
114
|
+
|
115
|
+
it 'returns false' do
|
116
|
+
expect(authenticator.authenticated?(controller)).to be false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#validate_configuration' do
|
122
|
+
context 'with valid configuration' do
|
123
|
+
it 'returns no errors' do
|
124
|
+
errors = authenticator.validate_configuration(options)
|
125
|
+
expect(errors).to be_empty
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'with invalid user class' do
|
130
|
+
let(:invalid_options) { { user_class: 'NonExistentUser' } }
|
131
|
+
|
132
|
+
it 'returns validation errors' do
|
133
|
+
errors = authenticator.validate_configuration(invalid_options)
|
134
|
+
expect(errors).to include(/not found/)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# TODO: Add more validation test cases based on your specific requirements
|
139
|
+
# Examples:
|
140
|
+
# context 'when required option is missing' do
|
141
|
+
# let(:invalid_options) { options.except(:required_option) }
|
142
|
+
#
|
143
|
+
# it 'returns validation error' do
|
144
|
+
# errors = authenticator.validate_configuration(invalid_options)
|
145
|
+
# expect(errors).to include(/required/)
|
146
|
+
# end
|
147
|
+
# end
|
148
|
+
end
|
149
|
+
|
150
|
+
describe 'interface compliance' do
|
151
|
+
it 'includes the authentication interface' do
|
152
|
+
expect(described_class.included_modules).to include(Tasker::Authentication::Interface)
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'responds to required interface methods' do
|
156
|
+
expect(authenticator).to respond_to(:authenticate!)
|
157
|
+
expect(authenticator).to respond_to(:current_user)
|
158
|
+
expect(authenticator).to respond_to(:authenticated?)
|
159
|
+
expect(authenticator).to respond_to(:validate_configuration)
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
---
|
2
|
+
# <%= application_name.humanize %> Custom Events Configuration
|
3
|
+
# Define your application-specific events here
|
4
|
+
# The system automatically protects against namespace collisions
|
5
|
+
|
6
|
+
events:
|
7
|
+
# Example order processing events
|
8
|
+
custom:
|
9
|
+
order_processed:
|
10
|
+
constant: "order.processed"
|
11
|
+
description: "Fired when an order is fully processed and ready for fulfillment"
|
12
|
+
payload_schema:
|
13
|
+
order_id: { type: "String", required: true }
|
14
|
+
customer_id: { type: "String", required: true }
|
15
|
+
total_amount: { type: "Float", required: true }
|
16
|
+
timestamp: { type: "Time", required: true }
|
17
|
+
fired_by: ["OrderService"]
|
18
|
+
|
19
|
+
payment_completed:
|
20
|
+
constant: "payment.completed"
|
21
|
+
description: "Fired when a payment is successfully processed"
|
22
|
+
payload_schema:
|
23
|
+
payment_id: { type: "String", required: true }
|
24
|
+
order_id: { type: "String", required: true }
|
25
|
+
amount: { type: "Float", required: true }
|
26
|
+
payment_method: { type: "String", required: true }
|
27
|
+
timestamp: { type: "Time", required: true }
|
28
|
+
fired_by: ["PaymentService"]
|
29
|
+
|
30
|
+
notification_sent:
|
31
|
+
constant: "notification.sent"
|
32
|
+
description: "Fired when a notification is successfully sent"
|
33
|
+
payload_schema:
|
34
|
+
notification_id: { type: "String", required: true }
|
35
|
+
recipient: { type: "String", required: true }
|
36
|
+
channel: { type: "String", required: true }
|
37
|
+
success: { type: "Boolean", required: true }
|
38
|
+
timestamp: { type: "Time", required: true }
|
39
|
+
fired_by: ["NotificationService"]
|
40
|
+
|
41
|
+
# Uncomment and customize these examples for your application:
|
42
|
+
#
|
43
|
+
# user_registered:
|
44
|
+
# constant: "user.registered"
|
45
|
+
# description: "Fired when a new user completes registration"
|
46
|
+
# payload_schema:
|
47
|
+
# user_id: { type: "String", required: true }
|
48
|
+
# email: { type: "String", required: true }
|
49
|
+
# registration_source: { type: "String", required: true }
|
50
|
+
# timestamp: { type: "Time", required: true }
|
51
|
+
# fired_by: ["UserService", "RegistrationController"]
|
52
|
+
#
|
53
|
+
# data_exported:
|
54
|
+
# constant: "data.exported"
|
55
|
+
# description: "Fired when data export is completed"
|
56
|
+
# payload_schema:
|
57
|
+
# export_id: { type: "String", required: true }
|
58
|
+
# format: { type: "String", required: true }
|
59
|
+
# record_count: { type: "Integer", required: true }
|
60
|
+
# file_size: { type: "Integer", required: false }
|
61
|
+
# timestamp: { type: "Time", required: true }
|
62
|
+
# fired_by: ["ExportService"]
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Example Custom Events Subscriber for <%= application_name.humanize %>
|
4
|
+
#
|
5
|
+
# This subscriber demonstrates how to create custom event handlers
|
6
|
+
# for your application-specific events.
|
7
|
+
class CustomEventsSubscriber < Tasker::Events::Subscribers::BaseSubscriber
|
8
|
+
# Subscribe to custom events defined in config/tasker/events.yml
|
9
|
+
# Note: Use clean event names - the system handles namespace protection internally
|
10
|
+
subscribe_to 'order.processed',
|
11
|
+
'payment.completed',
|
12
|
+
'notification.sent'
|
13
|
+
|
14
|
+
# Handle order processed events
|
15
|
+
def handle_order_processed(event)
|
16
|
+
order_id = safe_get(event, :order_id)
|
17
|
+
customer_id = safe_get(event, :customer_id)
|
18
|
+
total_amount = safe_get(event, :total_amount)
|
19
|
+
|
20
|
+
Rails.logger.info("Order #{order_id} processed for customer #{customer_id}, total: $#{total_amount}")
|
21
|
+
|
22
|
+
# Example: Send completion notification
|
23
|
+
# OrderCompletionMailer.order_processed(order_id).deliver_later
|
24
|
+
|
25
|
+
# Example: Update analytics
|
26
|
+
# Analytics.track_order_completion(order_id: order_id, amount: total_amount)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Handle payment completion events
|
30
|
+
def handle_payment_completed(event)
|
31
|
+
payment_id = safe_get(event, :payment_id)
|
32
|
+
order_id = safe_get(event, :order_id)
|
33
|
+
payment_method = safe_get(event, :payment_method)
|
34
|
+
|
35
|
+
Rails.logger.info("Payment #{payment_id} completed for order #{order_id} via #{payment_method}")
|
36
|
+
|
37
|
+
# Example: Record payment metrics
|
38
|
+
# PaymentMetrics.record_completion(payment_id: payment_id, method: payment_method)
|
39
|
+
|
40
|
+
# Example: Trigger fulfillment
|
41
|
+
# FulfillmentService.process_order(order_id)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Handle notification sent events
|
45
|
+
def handle_notification_sent(event)
|
46
|
+
notification_id = safe_get(event, :notification_id)
|
47
|
+
recipient = safe_get(event, :recipient)
|
48
|
+
channel = safe_get(event, :channel)
|
49
|
+
success = safe_get(event, :success)
|
50
|
+
|
51
|
+
if success
|
52
|
+
Rails.logger.info("Notification #{notification_id} sent to #{recipient} via #{channel}")
|
53
|
+
|
54
|
+
# Example: Update delivery metrics
|
55
|
+
# NotificationMetrics.record_delivery(notification_id: notification_id, channel: channel)
|
56
|
+
else
|
57
|
+
Rails.logger.warn("Failed to send notification #{notification_id} to #{recipient}")
|
58
|
+
|
59
|
+
# Example: Retry or escalate
|
60
|
+
# NotificationRetryService.schedule_retry(notification_id)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Optional: Override to add subscriber-specific filtering
|
65
|
+
# def should_process_event?(event_constant)
|
66
|
+
# # Only process events during business hours
|
67
|
+
# Time.current.hour.between?(9, 17)
|
68
|
+
# end
|
69
|
+
end
|
70
|
+
|
71
|
+
# Register the subscriber (add this to an initializer)
|
72
|
+
# CustomEventsSubscriber.subscribe(Tasker::Events::Publisher.instance)
|
@@ -0,0 +1,101 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Devise authenticator for <%= class_name %>
|
4
|
+
# Generated by: rails generate tasker:authenticator <%= file_name %> --type=devise
|
5
|
+
#
|
6
|
+
# This authenticator integrates with Devise authentication system.
|
7
|
+
# Uses Devise's built-in authentication methods and scopes.
|
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
|
+
# scope: :user
|
16
|
+
# }
|
17
|
+
# end
|
18
|
+
# end
|
19
|
+
|
20
|
+
class <%= class_name %>Authenticator
|
21
|
+
include Tasker::Authentication::Interface
|
22
|
+
|
23
|
+
def initialize(options = {})
|
24
|
+
@scope = options[:scope] || :user
|
25
|
+
@failure_app = options[:failure_app]
|
26
|
+
@options = options
|
27
|
+
end
|
28
|
+
|
29
|
+
# Required: Authenticate the request, raise exception if fails
|
30
|
+
def authenticate!(controller)
|
31
|
+
# Use Devise's built-in authentication
|
32
|
+
result = controller.send("authenticate_#{@scope}!")
|
33
|
+
|
34
|
+
# Devise authenticate_*! methods return true on success or redirect/halt on failure
|
35
|
+
# If we reach here, authentication was successful
|
36
|
+
result
|
37
|
+
rescue StandardError => e
|
38
|
+
# Devise authentication failed
|
39
|
+
raise Tasker::Authentication::AuthenticationError,
|
40
|
+
"Devise authentication failed: #{e.message}"
|
41
|
+
end
|
42
|
+
|
43
|
+
# Required: Get the current authenticated user
|
44
|
+
def current_user(controller)
|
45
|
+
# Use Devise's current_user helper
|
46
|
+
controller.send("current_#{@scope}")
|
47
|
+
rescue StandardError => e
|
48
|
+
Rails.logger.error "Error getting current #{@scope}: #{e.message}"
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
|
52
|
+
# Optional: Check if user is authenticated
|
53
|
+
def authenticated?(controller)
|
54
|
+
# Use Devise's user_signed_in? helper if available
|
55
|
+
signed_in_method = "#{@scope}_signed_in?"
|
56
|
+
|
57
|
+
if controller.respond_to?(signed_in_method)
|
58
|
+
controller.send(signed_in_method)
|
59
|
+
else
|
60
|
+
# Fallback to checking current_user presence
|
61
|
+
current_user(controller).present?
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Optional: Configuration validation
|
66
|
+
def validate_configuration(options = {})
|
67
|
+
errors = []
|
68
|
+
|
69
|
+
# Check if Devise is available
|
70
|
+
unless defined?(Devise)
|
71
|
+
errors << 'Devise gem is required for DeviseAuthenticator'
|
72
|
+
end
|
73
|
+
|
74
|
+
# Validate scope
|
75
|
+
scope = options[:scope] || :user
|
76
|
+
unless scope.is_a?(Symbol)
|
77
|
+
errors << 'Devise scope must be a symbol'
|
78
|
+
end
|
79
|
+
|
80
|
+
# Check if scope is configured in Devise
|
81
|
+
if defined?(Devise) && Devise.mappings[scope].nil?
|
82
|
+
errors << "Devise scope '#{scope}' is not configured. Available scopes: #{Devise.mappings.keys.join(', ')}"
|
83
|
+
end
|
84
|
+
|
85
|
+
errors
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
attr_reader :scope, :failure_app, :options
|
91
|
+
|
92
|
+
# Helper method to get the user model class for the scope
|
93
|
+
def user_model_class
|
94
|
+
return nil unless defined?(Devise)
|
95
|
+
|
96
|
+
mapping = Devise.mappings[@scope]
|
97
|
+
mapping&.class_name&.constantize
|
98
|
+
rescue StandardError
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
end
|