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,469 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'singleton'
|
4
|
+
require 'tasker/cache_capabilities'
|
5
|
+
|
6
|
+
module Tasker
|
7
|
+
# Unified cache capability detection and strategy management
|
8
|
+
#
|
9
|
+
# This class consolidates cache store introspection from MetricsBackend and
|
10
|
+
# IntelligentCacheManager into a single, comprehensive system that:
|
11
|
+
#
|
12
|
+
# 1. Detects capabilities of all major Rails cache stores
|
13
|
+
# 2. Supports Solid Cache and other modern Rails cache stores
|
14
|
+
# 3. Provides extensibility for custom cache implementations
|
15
|
+
# 4. Offers a consistent API for cache strategy selection
|
16
|
+
#
|
17
|
+
# **Phase 2.1.1 Enhancement: Hybrid Cache Store Detection System**
|
18
|
+
# Combines frozen constants for built-in Rails cache stores with declared
|
19
|
+
# capabilities for custom cache stores, creating a robust and extensible architecture.
|
20
|
+
#
|
21
|
+
# Detection Priority Order:
|
22
|
+
# 1. Declared capabilities (highest priority) - explicit developer declarations
|
23
|
+
# 2. Built-in store constants - fast, reliable detection for known stores
|
24
|
+
# 3. Custom detectors - pattern-based registration for legacy compatibility
|
25
|
+
# 4. Runtime detection - conservative fallback for unknown stores
|
26
|
+
#
|
27
|
+
# @example Basic usage
|
28
|
+
# strategy = Tasker::CacheStrategy.detect
|
29
|
+
# strategy.coordination_mode # => :distributed_atomic
|
30
|
+
# strategy.supports?(:locking) # => true
|
31
|
+
#
|
32
|
+
# @example Custom detector registration
|
33
|
+
# Tasker::CacheStrategy.register_detector(/MyCache/, ->(store) {
|
34
|
+
# { distributed: true, custom_feature: true }
|
35
|
+
# })
|
36
|
+
#
|
37
|
+
# @example Custom cache store with capabilities
|
38
|
+
# class MyAwesomeCacheStore < ActiveSupport::Cache::Store
|
39
|
+
# include Tasker::CacheCapabilities
|
40
|
+
# supports_distributed_caching!
|
41
|
+
# supports_atomic_increment!
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # Configure Rails to use your custom store
|
45
|
+
# Rails.application.configure do
|
46
|
+
# config.cache_store = MyAwesomeCacheStore.new
|
47
|
+
# end
|
48
|
+
#
|
49
|
+
# @example Direct instantiation
|
50
|
+
# strategy = Tasker::CacheStrategy.new
|
51
|
+
class CacheStrategy
|
52
|
+
include Tasker::Concerns::StructuredLogging
|
53
|
+
|
54
|
+
# Cache store coordination strategies
|
55
|
+
COORDINATION_STRATEGIES = {
|
56
|
+
distributed_atomic: 'Full distributed coordination with atomic operations',
|
57
|
+
distributed_basic: 'Basic distributed coordination with read-modify-write',
|
58
|
+
local_only: 'Local-only coordination for single-process deployments'
|
59
|
+
}.freeze
|
60
|
+
|
61
|
+
# ✅ CONSTANTS: Official Rails cache store class names (validated against Rails 8.0+ docs)
|
62
|
+
# These provide O(1) lookup performance for built-in Rails cache stores
|
63
|
+
DISTRIBUTED_CACHE_STORES = %w[
|
64
|
+
ActiveSupport::Cache::RedisCacheStore
|
65
|
+
ActiveSupport::Cache::MemCacheStore
|
66
|
+
SolidCache::Store
|
67
|
+
].freeze
|
68
|
+
|
69
|
+
ATOMIC_INCREMENT_STORES = %w[
|
70
|
+
ActiveSupport::Cache::RedisCacheStore
|
71
|
+
ActiveSupport::Cache::MemCacheStore
|
72
|
+
SolidCache::Store
|
73
|
+
].freeze
|
74
|
+
|
75
|
+
LOCKING_CAPABLE_STORES = %w[
|
76
|
+
ActiveSupport::Cache::RedisCacheStore
|
77
|
+
SolidCache::Store
|
78
|
+
].freeze
|
79
|
+
|
80
|
+
LOCAL_CACHE_STORES = %w[
|
81
|
+
ActiveSupport::Cache::MemoryStore
|
82
|
+
ActiveSupport::Cache::FileStore
|
83
|
+
ActiveSupport::Cache::NullStore
|
84
|
+
].freeze
|
85
|
+
|
86
|
+
attr_reader :store, :store_class_name, :capabilities, :coordination_mode, :instance_id
|
87
|
+
|
88
|
+
# Detect cache strategy for the current Rails.cache store
|
89
|
+
#
|
90
|
+
# @return [Tasker::CacheStrategy] Strategy instance for Rails.cache
|
91
|
+
def self.detect
|
92
|
+
new
|
93
|
+
end
|
94
|
+
|
95
|
+
# Register a custom cache store detector
|
96
|
+
#
|
97
|
+
# @param pattern [Regexp, String] Pattern to match store class names
|
98
|
+
# @param detector [Proc] Detector that returns capabilities hash
|
99
|
+
def self.register_detector(pattern, detector)
|
100
|
+
DetectorRegistry.instance.register_detector(pattern, detector)
|
101
|
+
end
|
102
|
+
|
103
|
+
# Clear all registered detectors (primarily for testing)
|
104
|
+
def self.clear_detectors!
|
105
|
+
DetectorRegistry.instance.clear_detectors!
|
106
|
+
end
|
107
|
+
|
108
|
+
# Create a strategy for the current Rails.cache store
|
109
|
+
#
|
110
|
+
# The cache strategy always analyzes Rails.cache, which is the single source
|
111
|
+
# of truth for caching in Rails applications. Custom cache stores should be
|
112
|
+
# configured through Rails.cache and declare their capabilities via the
|
113
|
+
# CacheCapabilities module.
|
114
|
+
def initialize
|
115
|
+
@detector_registry = DetectorRegistry.instance
|
116
|
+
@instance_id = generate_instance_id
|
117
|
+
|
118
|
+
# Handle Rails.cache unavailability gracefully
|
119
|
+
begin
|
120
|
+
@store = Rails.cache
|
121
|
+
@store_class_name = @store.class.name
|
122
|
+
rescue StandardError => e
|
123
|
+
log_structured(:warn, 'Rails.cache unavailable, using fallback configuration',
|
124
|
+
error: e.message,
|
125
|
+
instance_id: @instance_id)
|
126
|
+
@store = nil
|
127
|
+
@store_class_name = 'Unknown'
|
128
|
+
@capabilities = default_capabilities
|
129
|
+
@coordination_mode = :local_only
|
130
|
+
return
|
131
|
+
end
|
132
|
+
|
133
|
+
# Generate cache key that includes store configuration
|
134
|
+
cache_key = generate_cache_key(@store, @store_class_name)
|
135
|
+
|
136
|
+
# Check for cached strategy first
|
137
|
+
cached = @detector_registry.cached_strategy_for(cache_key)
|
138
|
+
if cached
|
139
|
+
@capabilities = cached.capabilities
|
140
|
+
@coordination_mode = cached.coordination_mode
|
141
|
+
else
|
142
|
+
# Detect capabilities with error handling
|
143
|
+
begin
|
144
|
+
@capabilities = detect_capabilities
|
145
|
+
@coordination_mode = select_coordination_strategy
|
146
|
+
|
147
|
+
# Cache this strategy instance
|
148
|
+
@detector_registry.cache_strategy_for(cache_key, self)
|
149
|
+
rescue StandardError => e
|
150
|
+
log_structured(:warn, 'Cache detection failed',
|
151
|
+
error: e.message,
|
152
|
+
store_class: @store_class_name,
|
153
|
+
instance_id: @instance_id)
|
154
|
+
log_structured(:warn, 'Falling back to local-only mode')
|
155
|
+
@store_class_name = 'Unknown'
|
156
|
+
@capabilities = default_capabilities
|
157
|
+
@coordination_mode = :local_only
|
158
|
+
return
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
log_strategy_detection
|
163
|
+
end
|
164
|
+
|
165
|
+
# Check if store supports a specific capability
|
166
|
+
#
|
167
|
+
# @param capability [Symbol] Capability to check (:distributed, :atomic_increment, etc.)
|
168
|
+
# @return [Boolean] True if capability is supported
|
169
|
+
def supports?(capability)
|
170
|
+
@capabilities[capability] || false
|
171
|
+
end
|
172
|
+
|
173
|
+
# Export capabilities for backward compatibility
|
174
|
+
#
|
175
|
+
# @return [Hash] Hash of capabilities for legacy integrations
|
176
|
+
def export_capabilities
|
177
|
+
@capabilities.dup
|
178
|
+
end
|
179
|
+
|
180
|
+
private
|
181
|
+
|
182
|
+
# Generate unique instance identifier for distributed coordination
|
183
|
+
#
|
184
|
+
# @return [String] Hostname-PID identifier
|
185
|
+
def generate_instance_id
|
186
|
+
hostname = begin
|
187
|
+
ENV['HOSTNAME'] || Socket.gethostname
|
188
|
+
rescue StandardError
|
189
|
+
'unknown'
|
190
|
+
end
|
191
|
+
"#{hostname}-#{Process.pid}"
|
192
|
+
end
|
193
|
+
|
194
|
+
# Generate cache key that includes store configuration
|
195
|
+
#
|
196
|
+
# @param store [ActiveSupport::Cache::Store] Rails cache store
|
197
|
+
# @param store_class_name [String] Store class name
|
198
|
+
# @return [String] Cache key that includes relevant configuration
|
199
|
+
def generate_cache_key(store, store_class_name)
|
200
|
+
key_parts = [store_class_name]
|
201
|
+
|
202
|
+
# Include namespace in cache key if present
|
203
|
+
if store.respond_to?(:options) && store.options.key?(:namespace)
|
204
|
+
key_parts << "namespace:#{store.options[:namespace]}"
|
205
|
+
end
|
206
|
+
|
207
|
+
# Include compression in cache key if present
|
208
|
+
if store.respond_to?(:options) && store.options.key?(:compress)
|
209
|
+
key_parts << "compress:#{store.options[:compress]}"
|
210
|
+
end
|
211
|
+
|
212
|
+
key_parts.join('|')
|
213
|
+
rescue StandardError
|
214
|
+
# Fallback to just class name if options access fails
|
215
|
+
store_class_name
|
216
|
+
end
|
217
|
+
|
218
|
+
# Detect cache store capabilities using hybrid detection system
|
219
|
+
#
|
220
|
+
# Detection Priority Order:
|
221
|
+
# 1. Declared capabilities (highest priority) - explicit developer declarations
|
222
|
+
# 2. Built-in store constants - fast, reliable detection for known stores
|
223
|
+
# 3. Custom detectors - pattern-based registration for legacy compatibility
|
224
|
+
# 4. Runtime detection - conservative fallback for unknown stores
|
225
|
+
#
|
226
|
+
# @return [Hash] Detected capabilities
|
227
|
+
def detect_capabilities
|
228
|
+
return default_capabilities unless rails_cache_available?
|
229
|
+
|
230
|
+
capabilities = {}
|
231
|
+
|
232
|
+
# Priority 1: Check for declared capabilities via CacheCapabilities module
|
233
|
+
declared_capabilities = detect_declared_capabilities
|
234
|
+
if declared_capabilities.any?
|
235
|
+
log_structured(:debug, 'Using declared cache capabilities',
|
236
|
+
store_class: @store_class_name,
|
237
|
+
declared_capabilities: declared_capabilities)
|
238
|
+
capabilities.merge!(declared_capabilities)
|
239
|
+
end
|
240
|
+
|
241
|
+
# Priority 2: Apply custom detectors (higher priority than built-in constants)
|
242
|
+
custom_capabilities = apply_custom_detectors
|
243
|
+
capabilities.merge!(custom_capabilities) { |_key, declared, custom| declared.nil? ? custom : declared }
|
244
|
+
|
245
|
+
# Priority 3: Use built-in store constants for remaining capabilities
|
246
|
+
builtin_capabilities = detect_builtin_store_capabilities
|
247
|
+
capabilities.merge!(builtin_capabilities) { |_key, existing, builtin| existing.nil? ? builtin : existing }
|
248
|
+
|
249
|
+
# Priority 4: Runtime detection fallback for any missing capabilities
|
250
|
+
runtime_capabilities = detect_runtime_capabilities
|
251
|
+
capabilities.merge!(runtime_capabilities) { |_key, existing, runtime| existing.nil? ? runtime : existing }
|
252
|
+
|
253
|
+
# Ensure all expected capabilities are present
|
254
|
+
capabilities.merge!(default_capabilities) { |_key, detected, default| detected.nil? ? default : detected }
|
255
|
+
|
256
|
+
capabilities
|
257
|
+
rescue StandardError => e
|
258
|
+
log_structured(:error, 'Cache capability detection failed',
|
259
|
+
error: e.message,
|
260
|
+
store_class: @store_class_name,
|
261
|
+
instance_id: @instance_id)
|
262
|
+
default_capabilities
|
263
|
+
end
|
264
|
+
|
265
|
+
# Priority 1: Detect capabilities declared via CacheCapabilities module
|
266
|
+
#
|
267
|
+
# @return [Hash] Declared capabilities from CacheCapabilities module
|
268
|
+
def detect_declared_capabilities
|
269
|
+
return {} unless @store.class.respond_to?(:declared_cache_capabilities)
|
270
|
+
|
271
|
+
declared = @store.class.declared_cache_capabilities
|
272
|
+
return {} unless declared.is_a?(Hash) && declared.any?
|
273
|
+
|
274
|
+
# Convert to our standard capability format
|
275
|
+
capabilities = {}
|
276
|
+
declared.each do |capability, supported|
|
277
|
+
capabilities[capability.to_sym] = supported
|
278
|
+
end
|
279
|
+
|
280
|
+
capabilities
|
281
|
+
rescue StandardError => e
|
282
|
+
log_structured(:warn, 'Failed to detect declared capabilities',
|
283
|
+
error: e.message,
|
284
|
+
store_class: @store_class_name)
|
285
|
+
{}
|
286
|
+
end
|
287
|
+
|
288
|
+
# Priority 3: Detect capabilities using built-in store constants
|
289
|
+
#
|
290
|
+
# @return [Hash] Capabilities detected from frozen constants
|
291
|
+
def detect_builtin_store_capabilities
|
292
|
+
capabilities = {
|
293
|
+
distributed: DISTRIBUTED_CACHE_STORES.include?(@store_class_name),
|
294
|
+
atomic_increment: ATOMIC_INCREMENT_STORES.include?(@store_class_name),
|
295
|
+
locking: LOCKING_CAPABLE_STORES.include?(@store_class_name),
|
296
|
+
ttl_inspection: DISTRIBUTED_CACHE_STORES.include?(@store_class_name), # Most distributed stores support TTL
|
297
|
+
namespace_support: nil, # Will be detected at runtime
|
298
|
+
compression_support: nil, # Will be detected at runtime
|
299
|
+
key_transformation: true, # All Rails cache stores transform keys
|
300
|
+
store_class: @store_class_name
|
301
|
+
}
|
302
|
+
|
303
|
+
# Remove nil values so they can be filled by lower-priority detection
|
304
|
+
capabilities.compact
|
305
|
+
end
|
306
|
+
|
307
|
+
# Priority 4: Runtime detection fallback for missing capabilities
|
308
|
+
#
|
309
|
+
# Uses our frozen constants plus runtime introspection for non-capability features
|
310
|
+
# @return [Hash] Runtime-detected capabilities
|
311
|
+
def detect_runtime_capabilities
|
312
|
+
{
|
313
|
+
# Use frozen constants (much more reliable than pattern matching)
|
314
|
+
distributed: DISTRIBUTED_CACHE_STORES.include?(@store_class_name),
|
315
|
+
atomic_increment: ATOMIC_INCREMENT_STORES.include?(@store_class_name),
|
316
|
+
locking: LOCKING_CAPABLE_STORES.include?(@store_class_name),
|
317
|
+
ttl_inspection: DISTRIBUTED_CACHE_STORES.include?(@store_class_name), # Most distributed stores support TTL
|
318
|
+
# These require actual runtime introspection
|
319
|
+
namespace_support: namespace_support?(@store),
|
320
|
+
compression_support: compression_support?(@store),
|
321
|
+
key_transformation: true, # All Rails cache stores transform keys
|
322
|
+
store_class: @store_class_name
|
323
|
+
}
|
324
|
+
end
|
325
|
+
|
326
|
+
# Priority 2: Apply custom detectors to the store
|
327
|
+
#
|
328
|
+
# @return [Hash] Custom capabilities detected
|
329
|
+
def apply_custom_detectors
|
330
|
+
custom_capabilities = {}
|
331
|
+
|
332
|
+
@detector_registry.custom_detectors.each do |pattern, detector|
|
333
|
+
next unless pattern.is_a?(Regexp) ? pattern.match?(@store_class_name) : @store_class_name.include?(pattern.to_s)
|
334
|
+
|
335
|
+
begin
|
336
|
+
detected = detector.call(@store)
|
337
|
+
custom_capabilities.merge!(detected) if detected.is_a?(Hash)
|
338
|
+
rescue StandardError => e
|
339
|
+
log_structured(:warn, 'Custom detector failed',
|
340
|
+
pattern: pattern.inspect,
|
341
|
+
error: e.message,
|
342
|
+
store_class: @store_class_name)
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
custom_capabilities
|
347
|
+
end
|
348
|
+
|
349
|
+
# Check if cache store supports namespacing
|
350
|
+
#
|
351
|
+
# @param store [ActiveSupport::Cache::Store] Rails cache store
|
352
|
+
# @return [Boolean] True if namespace is supported
|
353
|
+
def namespace_support?(store)
|
354
|
+
store.respond_to?(:options) && store.options.key?(:namespace)
|
355
|
+
rescue StandardError
|
356
|
+
false
|
357
|
+
end
|
358
|
+
|
359
|
+
# Check if cache store supports compression
|
360
|
+
#
|
361
|
+
# @param store [ActiveSupport::Cache::Store] Rails cache store
|
362
|
+
# @return [Boolean] True if compression is supported
|
363
|
+
def compression_support?(store)
|
364
|
+
store.respond_to?(:options) && store.options.key?(:compress)
|
365
|
+
rescue StandardError
|
366
|
+
false
|
367
|
+
end
|
368
|
+
|
369
|
+
# Select coordination strategy based on detected capabilities
|
370
|
+
#
|
371
|
+
# @return [Symbol] Selected coordination strategy
|
372
|
+
def select_coordination_strategy
|
373
|
+
case @capabilities
|
374
|
+
in { distributed: true, atomic_increment: true, locking: true }
|
375
|
+
:distributed_atomic # Redis/SolidCache with full features
|
376
|
+
in { distributed: true, atomic_increment: true }
|
377
|
+
:distributed_basic # Redis/Memcached without locking
|
378
|
+
in { distributed: true }
|
379
|
+
:distributed_basic # Basic distributed cache
|
380
|
+
else
|
381
|
+
:local_only # Memory/File store - no cross-process sync
|
382
|
+
end
|
383
|
+
end
|
384
|
+
|
385
|
+
# Default capabilities for unknown or failed detection
|
386
|
+
#
|
387
|
+
# @return [Hash] Safe default capabilities
|
388
|
+
def default_capabilities
|
389
|
+
{
|
390
|
+
distributed: false,
|
391
|
+
atomic_increment: false,
|
392
|
+
locking: false,
|
393
|
+
ttl_inspection: false,
|
394
|
+
namespace_support: false,
|
395
|
+
compression_support: false,
|
396
|
+
key_transformation: true,
|
397
|
+
store_class: @store_class_name
|
398
|
+
}
|
399
|
+
end
|
400
|
+
|
401
|
+
# Check if Rails.cache is available and functional
|
402
|
+
#
|
403
|
+
# @return [Boolean] True if Rails.cache is available
|
404
|
+
def rails_cache_available?
|
405
|
+
return false if @store.nil?
|
406
|
+
|
407
|
+
defined?(Rails) && @store.respond_to?(:read) && @store.respond_to?(:write)
|
408
|
+
rescue StandardError
|
409
|
+
false
|
410
|
+
end
|
411
|
+
|
412
|
+
# Log strategy detection results
|
413
|
+
def log_strategy_detection
|
414
|
+
log_structured(:info, 'Cache strategy detected',
|
415
|
+
store_class: @store_class_name,
|
416
|
+
coordination_strategy: @coordination_mode,
|
417
|
+
capabilities: @capabilities,
|
418
|
+
instance_id: @instance_id)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
422
|
+
# Singleton registry for managing custom detectors and caching strategies
|
423
|
+
class DetectorRegistry
|
424
|
+
include Singleton
|
425
|
+
|
426
|
+
def initialize
|
427
|
+
@custom_detectors = {}
|
428
|
+
@strategy_cache = {}
|
429
|
+
@cache_mutex = Mutex.new
|
430
|
+
end
|
431
|
+
|
432
|
+
# Register a custom cache store detector
|
433
|
+
#
|
434
|
+
# @param pattern [Regexp, String] Pattern to match store class names
|
435
|
+
# @param detector [Proc] Detector that returns capabilities hash
|
436
|
+
def register_detector(pattern, detector)
|
437
|
+
@cache_mutex.synchronize do
|
438
|
+
@custom_detectors[pattern] = detector
|
439
|
+
@strategy_cache.clear # Clear cache when detectors change
|
440
|
+
end
|
441
|
+
end
|
442
|
+
|
443
|
+
# Clear all registered detectors (primarily for testing)
|
444
|
+
def clear_detectors!
|
445
|
+
@cache_mutex.synchronize do
|
446
|
+
@custom_detectors.clear
|
447
|
+
@strategy_cache.clear
|
448
|
+
end
|
449
|
+
end
|
450
|
+
|
451
|
+
# Get custom detectors (thread-safe read access)
|
452
|
+
def custom_detectors
|
453
|
+
@cache_mutex.synchronize { @custom_detectors.dup }
|
454
|
+
end
|
455
|
+
|
456
|
+
# Cache strategy instances for performance
|
457
|
+
def cached_strategy_for(store_class_name)
|
458
|
+
@cache_mutex.synchronize do
|
459
|
+
@strategy_cache[store_class_name]
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
463
|
+
def cache_strategy_for(store_class_name, strategy_instance)
|
464
|
+
@cache_mutex.synchronize do
|
465
|
+
@strategy_cache[store_class_name] = strategy_instance
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../authentication/coordinator'
|
4
|
+
|
5
|
+
module Tasker
|
6
|
+
module Concerns
|
7
|
+
module Authenticatable
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
included do
|
11
|
+
before_action :authenticate_tasker_user!, unless: :skip_authentication?
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def authenticate_tasker_user!
|
17
|
+
return true if skip_authentication?
|
18
|
+
|
19
|
+
Tasker::Authentication::Coordinator.authenticate!(self)
|
20
|
+
rescue Tasker::Authentication::AuthenticationError => e
|
21
|
+
# Only render response if we're in a real controller context
|
22
|
+
# In unit tests, let the exception bubble up for testing
|
23
|
+
raise unless respond_to?(:render) && respond_to?(:request)
|
24
|
+
|
25
|
+
render json: { error: 'Unauthorized', message: e.message }, status: :unauthorized
|
26
|
+
end
|
27
|
+
|
28
|
+
def current_tasker_user
|
29
|
+
@current_tasker_user ||= Tasker::Authentication::Coordinator.current_user(self)
|
30
|
+
end
|
31
|
+
|
32
|
+
def tasker_user_authenticated?
|
33
|
+
Tasker::Authentication::Coordinator.authenticated?(self)
|
34
|
+
end
|
35
|
+
|
36
|
+
def skip_authentication?
|
37
|
+
!Tasker.configuration.auth.authentication_enabled
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|