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,333 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../registry/base_registry'
|
4
|
+
require_relative '../registry/interface_validator'
|
5
|
+
require 'concurrent-ruby'
|
6
|
+
|
7
|
+
module Tasker
|
8
|
+
module Telemetry
|
9
|
+
# Registry for managing export plugins
|
10
|
+
#
|
11
|
+
# Provides centralized management of export plugins with discovery,
|
12
|
+
# registration, and format-based lookup capabilities. Now modernized
|
13
|
+
# with BaseRegistry patterns for consistency across all registry systems.
|
14
|
+
#
|
15
|
+
# @example Register a plugin
|
16
|
+
# registry = Tasker::Telemetry::PluginRegistry.instance
|
17
|
+
# registry.register('my_exporter', MyExporter.new)
|
18
|
+
#
|
19
|
+
# @example Find plugins by format
|
20
|
+
# json_plugins = registry.find_by_format('json')
|
21
|
+
# csv_plugins = registry.find_by_format('csv')
|
22
|
+
#
|
23
|
+
# @example Auto-discover plugins
|
24
|
+
# registry.auto_discover_plugins
|
25
|
+
class PluginRegistry < Registry::BaseRegistry
|
26
|
+
include Singleton
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
super
|
30
|
+
@plugins = Concurrent::Hash.new
|
31
|
+
@formats = Concurrent::Hash.new
|
32
|
+
log_registry_operation('initialized', total_plugins: 0, total_formats: 0)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Register a plugin
|
36
|
+
#
|
37
|
+
# @param name [String, Symbol] Plugin identifier
|
38
|
+
# @param plugin [Object] Plugin instance
|
39
|
+
# @param replace [Boolean] Whether to replace existing plugin
|
40
|
+
# @param options [Hash] Plugin options
|
41
|
+
# @return [Boolean] True if registration successful
|
42
|
+
def register(name, plugin, replace: false, **options)
|
43
|
+
name = name.to_s
|
44
|
+
|
45
|
+
thread_safe_operation do
|
46
|
+
# Validate plugin interface
|
47
|
+
begin
|
48
|
+
Registry::InterfaceValidator.validate_plugin!(plugin)
|
49
|
+
rescue ArgumentError => e
|
50
|
+
log_validation_failure('telemetry_plugin', name, e.message)
|
51
|
+
raise
|
52
|
+
end
|
53
|
+
|
54
|
+
# Check for existing plugin
|
55
|
+
if @plugins.key?(name) && !replace
|
56
|
+
raise ArgumentError, "Plugin '#{name}' already registered. Use replace: true to override."
|
57
|
+
end
|
58
|
+
|
59
|
+
# Remove existing plugin if replacing
|
60
|
+
if @plugins.key?(name)
|
61
|
+
existing_config = @plugins[name]
|
62
|
+
unregister_format_mappings(name, existing_config[:supported_formats])
|
63
|
+
log_unregistration('telemetry_plugin', name, existing_config[:instance].class)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Get supported formats
|
67
|
+
supported_formats = get_supported_formats(plugin)
|
68
|
+
|
69
|
+
# Register plugin
|
70
|
+
plugin_config = {
|
71
|
+
instance: plugin,
|
72
|
+
name: name,
|
73
|
+
options: options.merge(replace: replace),
|
74
|
+
registered_at: Time.current,
|
75
|
+
supported_formats: supported_formats
|
76
|
+
}
|
77
|
+
|
78
|
+
@plugins[name] = plugin_config
|
79
|
+
|
80
|
+
# Index by supported formats
|
81
|
+
register_format_mappings(name, supported_formats)
|
82
|
+
|
83
|
+
log_registration('telemetry_plugin', name, plugin.class,
|
84
|
+
{ supported_formats: supported_formats, format_count: supported_formats.size, **options })
|
85
|
+
|
86
|
+
true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Unregister a plugin
|
91
|
+
#
|
92
|
+
# @param name [String, Symbol] Plugin identifier
|
93
|
+
# @return [Boolean] True if unregistered successfully
|
94
|
+
def unregister(name)
|
95
|
+
name = name.to_s
|
96
|
+
|
97
|
+
thread_safe_operation do
|
98
|
+
plugin_config = @plugins.delete(name)
|
99
|
+
|
100
|
+
if plugin_config
|
101
|
+
# Remove from format index
|
102
|
+
unregister_format_mappings(name, plugin_config[:supported_formats])
|
103
|
+
|
104
|
+
log_unregistration('telemetry_plugin', name, plugin_config[:instance].class)
|
105
|
+
true
|
106
|
+
else
|
107
|
+
false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# Get all registered plugins
|
113
|
+
#
|
114
|
+
# @return [Hash] Hash of plugin name => plugin info
|
115
|
+
def all_plugins
|
116
|
+
@plugins.dup
|
117
|
+
end
|
118
|
+
|
119
|
+
# Get all registered plugins (required by BaseRegistry)
|
120
|
+
#
|
121
|
+
# @return [Hash] All registered plugins
|
122
|
+
def all_items
|
123
|
+
all_plugins
|
124
|
+
end
|
125
|
+
|
126
|
+
# Get plugin by name
|
127
|
+
#
|
128
|
+
# @param name [String, Symbol] Plugin identifier
|
129
|
+
# @return [Object, nil] Plugin instance or nil if not found
|
130
|
+
def get_plugin(name)
|
131
|
+
plugin_config = @plugins[name.to_s]
|
132
|
+
plugin_config&.dig(:instance)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Find plugins that support a specific format
|
136
|
+
#
|
137
|
+
# @param format [String, Symbol] Format to search for
|
138
|
+
# @return [Array<Object>] Array of plugin instances
|
139
|
+
def find_by_format(format)
|
140
|
+
format = format.to_s.downcase
|
141
|
+
plugin_names = @formats[format].to_a
|
142
|
+
|
143
|
+
plugin_names.filter_map { |name| get_plugin(name) }
|
144
|
+
end
|
145
|
+
|
146
|
+
# Find plugins by criteria (supports keyword arguments for test compatibility)
|
147
|
+
#
|
148
|
+
# @param format [String, Symbol] Format to search for
|
149
|
+
# @return [Array<Object>] Array of plugin instances
|
150
|
+
def find_by(format:)
|
151
|
+
find_by_format(format)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Get supported formats across all plugins
|
155
|
+
#
|
156
|
+
# @return [Array<String>] Array of supported format names
|
157
|
+
def supported_formats
|
158
|
+
@formats.keys.sort
|
159
|
+
end
|
160
|
+
|
161
|
+
# Check if a format is supported by any plugin
|
162
|
+
#
|
163
|
+
# @param format [String, Symbol] Format to check
|
164
|
+
# @return [Boolean] True if format is supported
|
165
|
+
def supports_format?(format)
|
166
|
+
@formats.key?(format.to_s.downcase)
|
167
|
+
end
|
168
|
+
|
169
|
+
# Auto-discover plugins in the plugins directory
|
170
|
+
#
|
171
|
+
# @param directory [String] Directory to search for plugins
|
172
|
+
# @return [Integer] Number of plugins discovered
|
173
|
+
def auto_discover_plugins(directory = nil)
|
174
|
+
directory ||= File.join(File.dirname(__FILE__), 'plugins')
|
175
|
+
|
176
|
+
return 0 unless Dir.exist?(directory)
|
177
|
+
|
178
|
+
discovered_count = 0
|
179
|
+
|
180
|
+
Dir.glob(File.join(directory, '*_exporter.rb')).each do |file|
|
181
|
+
require file
|
182
|
+
|
183
|
+
# Extract class name from filename
|
184
|
+
class_name = File.basename(file, '.rb').camelize
|
185
|
+
full_class_name = "Tasker::Telemetry::Plugins::#{class_name}"
|
186
|
+
|
187
|
+
# Try to instantiate the plugin
|
188
|
+
plugin_class = full_class_name.constantize
|
189
|
+
plugin_instance = plugin_class.new
|
190
|
+
|
191
|
+
register(class_name.underscore, plugin_instance, auto_discovered: true)
|
192
|
+
discovered_count += 1
|
193
|
+
|
194
|
+
log_registry_operation('auto_discovered_plugin',
|
195
|
+
plugin_name: class_name,
|
196
|
+
plugin_class: full_class_name,
|
197
|
+
file_path: file)
|
198
|
+
rescue StandardError => e
|
199
|
+
log_registry_error('auto_discovery_failed', e,
|
200
|
+
file_path: file,
|
201
|
+
class_name: File.basename(file, '.rb').camelize)
|
202
|
+
end
|
203
|
+
|
204
|
+
discovered_count
|
205
|
+
end
|
206
|
+
|
207
|
+
# Get comprehensive registry statistics
|
208
|
+
#
|
209
|
+
# @return [Hash] Detailed statistics about the registry
|
210
|
+
def stats
|
211
|
+
base_stats.merge(
|
212
|
+
total_plugins: @plugins.size,
|
213
|
+
total_formats: @formats.size,
|
214
|
+
supported_formats: @formats.keys.sort,
|
215
|
+
plugins_by_format: @formats.transform_values(&:size),
|
216
|
+
average_formats_per_plugin: calculate_average_formats_per_plugin,
|
217
|
+
most_popular_formats: find_most_popular_formats,
|
218
|
+
plugin_distribution: calculate_plugin_distribution
|
219
|
+
)
|
220
|
+
end
|
221
|
+
|
222
|
+
# Clear all registered plugins (required by BaseRegistry)
|
223
|
+
#
|
224
|
+
# @return [Boolean] True if cleared successfully
|
225
|
+
def clear!
|
226
|
+
thread_safe_operation do
|
227
|
+
@plugins.clear
|
228
|
+
@formats.clear
|
229
|
+
log_registry_operation('cleared_all')
|
230
|
+
true
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
# Legacy method for backward compatibility
|
235
|
+
#
|
236
|
+
# @return [Boolean] True if cleared successfully
|
237
|
+
def clear_all!
|
238
|
+
clear!
|
239
|
+
end
|
240
|
+
|
241
|
+
private
|
242
|
+
|
243
|
+
# Register format mappings for a plugin
|
244
|
+
#
|
245
|
+
# @param plugin_name [String] Name of the plugin
|
246
|
+
# @param formats [Array<String>] Formats to map
|
247
|
+
def register_format_mappings(plugin_name, formats)
|
248
|
+
formats.each do |format|
|
249
|
+
format_key = format.to_s.downcase
|
250
|
+
@formats[format_key] ||= []
|
251
|
+
@formats[format_key] << plugin_name unless @formats[format_key].include?(plugin_name)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
# Unregister format mappings for a plugin
|
256
|
+
#
|
257
|
+
# @param plugin_name [String] Name of the plugin
|
258
|
+
# @param formats [Array<String>] Formats to unmap
|
259
|
+
def unregister_format_mappings(plugin_name, formats)
|
260
|
+
formats.each do |format|
|
261
|
+
format_key = format.to_s.downcase
|
262
|
+
@formats[format_key]&.delete(plugin_name)
|
263
|
+
@formats.delete(format_key) if @formats[format_key] && @formats[format_key].empty?
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
# Get supported formats from a plugin
|
268
|
+
#
|
269
|
+
# @param plugin [Object] Plugin instance
|
270
|
+
# @return [Array<String>] Array of supported formats
|
271
|
+
def get_supported_formats(plugin)
|
272
|
+
return [] unless plugin.respond_to?(:supported_formats)
|
273
|
+
|
274
|
+
formats = plugin.supported_formats
|
275
|
+
Array(formats).map(&:to_s).map(&:downcase).uniq
|
276
|
+
rescue StandardError => e
|
277
|
+
log_registry_error('format_discovery_failed', e,
|
278
|
+
plugin_class: plugin.class.name)
|
279
|
+
[]
|
280
|
+
end
|
281
|
+
|
282
|
+
# Calculate average formats per plugin
|
283
|
+
#
|
284
|
+
# @return [Float] Average number of formats per plugin
|
285
|
+
def calculate_average_formats_per_plugin
|
286
|
+
return 0.0 if @plugins.empty?
|
287
|
+
|
288
|
+
total_formats = @plugins.values.sum { |config| config[:supported_formats].size }
|
289
|
+
(total_formats.to_f / @plugins.size).round(2)
|
290
|
+
end
|
291
|
+
|
292
|
+
# Find the most popular formats (top 5)
|
293
|
+
#
|
294
|
+
# @return [Array<Hash>] Array of format popularity data
|
295
|
+
def find_most_popular_formats
|
296
|
+
@formats
|
297
|
+
.map { |format, plugins| { format: format, plugin_count: plugins.size } }
|
298
|
+
.sort_by { |data| -data[:plugin_count] }
|
299
|
+
.first(5)
|
300
|
+
end
|
301
|
+
|
302
|
+
# Calculate plugin distribution statistics
|
303
|
+
#
|
304
|
+
# @return [Hash] Distribution statistics
|
305
|
+
def calculate_plugin_distribution
|
306
|
+
formats_per_plugin = @plugins.values.map { |config| config[:supported_formats].size }
|
307
|
+
|
308
|
+
return { distribution: 'empty' } if formats_per_plugin.empty?
|
309
|
+
|
310
|
+
{
|
311
|
+
distribution: calculate_distribution_type(formats_per_plugin),
|
312
|
+
average_formats_per_plugin: calculate_average_formats_per_plugin,
|
313
|
+
max_formats_per_plugin: formats_per_plugin.max,
|
314
|
+
min_formats_per_plugin: formats_per_plugin.min
|
315
|
+
}
|
316
|
+
end
|
317
|
+
|
318
|
+
# Calculate distribution type based on formats per plugin
|
319
|
+
#
|
320
|
+
# @param formats_per_plugin [Array<Integer>] Array of format counts
|
321
|
+
# @return [String] Distribution type
|
322
|
+
def calculate_distribution_type(formats_per_plugin)
|
323
|
+
return 'empty' if formats_per_plugin.empty?
|
324
|
+
return 'uniform' if formats_per_plugin.uniq.size == 1
|
325
|
+
|
326
|
+
avg = formats_per_plugin.sum.to_f / formats_per_plugin.size
|
327
|
+
variance = formats_per_plugin.sum { |count| (count - avg)**2 } / formats_per_plugin.size
|
328
|
+
|
329
|
+
variance < 2 ? 'even' : 'varied'
|
330
|
+
end
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
@@ -0,0 +1,246 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tasker
|
4
|
+
module Telemetry
|
5
|
+
module Plugins
|
6
|
+
# Base class for telemetry export plugins
|
7
|
+
#
|
8
|
+
# Provides a standard interface and common functionality for all export plugins.
|
9
|
+
# Plugins should inherit from this class and implement the required methods.
|
10
|
+
#
|
11
|
+
# @example Creating a custom exporter
|
12
|
+
# class MyCustomExporter < Tasker::Telemetry::Plugins::BaseExporter
|
13
|
+
# def export(metrics_data, options = {})
|
14
|
+
# # Implementation here
|
15
|
+
# log_plugin_event(:info, "Custom export completed", metrics_count: metrics_data.size)
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def supports_format?(format)
|
19
|
+
# format.to_s == 'custom'
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
# def supported_formats
|
23
|
+
# ['custom']
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
class BaseExporter
|
27
|
+
include Tasker::Concerns::StructuredLogging
|
28
|
+
|
29
|
+
# Plugin metadata
|
30
|
+
attr_reader :name, :version, :description
|
31
|
+
|
32
|
+
def initialize(name: nil, version: '1.0.0', description: nil)
|
33
|
+
# Safe class name extraction for test environments where class.name might be nil
|
34
|
+
default_name = if self.class.name
|
35
|
+
self.class.name.demodulize.underscore
|
36
|
+
else
|
37
|
+
'anonymous_exporter'
|
38
|
+
end
|
39
|
+
|
40
|
+
@name = name || default_name
|
41
|
+
@version = version
|
42
|
+
@description = description || "#{@name} telemetry exporter"
|
43
|
+
end
|
44
|
+
|
45
|
+
# Export metrics data (must be implemented by subclasses)
|
46
|
+
#
|
47
|
+
# @param metrics_data [Hash] Metrics data to export
|
48
|
+
# @param options [Hash] Export options
|
49
|
+
# @return [Hash] Export result with :success, :format, :data keys
|
50
|
+
# @raise [NotImplementedError] If not implemented by subclass
|
51
|
+
def export(metrics_data, options = {})
|
52
|
+
raise NotImplementedError, "#{self.class.name} must implement #export method"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Check if plugin supports a specific format (must be implemented by subclasses)
|
56
|
+
#
|
57
|
+
# @param format [String, Symbol] Format to check
|
58
|
+
# @return [Boolean] Whether format is supported
|
59
|
+
# @raise [NotImplementedError] If not implemented by subclass
|
60
|
+
def supports_format?(format)
|
61
|
+
raise NotImplementedError, "#{self.class.name} must implement #supports_format? method"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Get supported formats (should be implemented by subclasses)
|
65
|
+
#
|
66
|
+
# @return [Array<String>] Supported export formats
|
67
|
+
def supported_formats
|
68
|
+
[]
|
69
|
+
end
|
70
|
+
|
71
|
+
# Plugin lifecycle callbacks (optional overrides)
|
72
|
+
|
73
|
+
# Called when cache sync occurs
|
74
|
+
#
|
75
|
+
# @param sync_data [Hash] Cache sync information
|
76
|
+
def on_cache_sync(sync_data)
|
77
|
+
# Default: no action
|
78
|
+
end
|
79
|
+
|
80
|
+
# Called when export is requested
|
81
|
+
#
|
82
|
+
# @param request_data [Hash] Export request information
|
83
|
+
def on_export_request(request_data)
|
84
|
+
# Default: no action
|
85
|
+
end
|
86
|
+
|
87
|
+
# Called when export completes
|
88
|
+
#
|
89
|
+
# @param completion_data [Hash] Export completion information
|
90
|
+
def on_export_complete(completion_data)
|
91
|
+
# Default: no action
|
92
|
+
end
|
93
|
+
|
94
|
+
# Safe export wrapper with error handling and timing
|
95
|
+
#
|
96
|
+
# @param metrics_data [Hash] Metrics data to export
|
97
|
+
# @param options [Hash] Export options
|
98
|
+
# @return [Hash] Export result with success/error information
|
99
|
+
def safe_export(metrics_data, options = {})
|
100
|
+
start_time = Time.current
|
101
|
+
|
102
|
+
begin
|
103
|
+
# Validate metrics data structure
|
104
|
+
validate_metrics_data!(metrics_data) if respond_to?(:validate_metrics_data!, true)
|
105
|
+
|
106
|
+
result = export(metrics_data, options)
|
107
|
+
|
108
|
+
duration = ((Time.current - start_time) * 1000).round(2)
|
109
|
+
|
110
|
+
log_plugin_event(:info, 'Plugin export completed',
|
111
|
+
metrics_count: metrics_data.size,
|
112
|
+
duration_ms: duration,
|
113
|
+
success: true)
|
114
|
+
|
115
|
+
{
|
116
|
+
success: true,
|
117
|
+
format: result[:format] || 'unknown',
|
118
|
+
data: result[:data],
|
119
|
+
result: result, # Include the full result for test compatibility
|
120
|
+
plugin: { name: @name, version: @version }, # Add plugin field for test compatibility
|
121
|
+
metrics_count: metrics_data.size,
|
122
|
+
duration_ms: duration,
|
123
|
+
plugin_name: @name,
|
124
|
+
plugin_version: @version
|
125
|
+
}
|
126
|
+
rescue StandardError => e
|
127
|
+
duration = ((Time.current - start_time) * 1000).round(2)
|
128
|
+
|
129
|
+
log_plugin_event(:error, 'Plugin export failed',
|
130
|
+
metrics_count: metrics_data.size,
|
131
|
+
duration_ms: duration,
|
132
|
+
error: e.message,
|
133
|
+
success: false)
|
134
|
+
|
135
|
+
{
|
136
|
+
success: false,
|
137
|
+
error: e.message,
|
138
|
+
metrics_count: metrics_data.size,
|
139
|
+
duration_ms: duration,
|
140
|
+
plugin_name: @name,
|
141
|
+
plugin_version: @version
|
142
|
+
}
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Get plugin metadata
|
147
|
+
#
|
148
|
+
# @return [Hash] Plugin metadata
|
149
|
+
def metadata
|
150
|
+
# Use class constants when available, otherwise use instance variables
|
151
|
+
version = if self.class.const_defined?(:VERSION)
|
152
|
+
self.class.const_get(:VERSION)
|
153
|
+
else
|
154
|
+
@version == '1.0.0' ? 'unknown' : @version
|
155
|
+
end
|
156
|
+
|
157
|
+
description = if self.class.const_defined?(:DESCRIPTION)
|
158
|
+
self.class.const_get(:DESCRIPTION)
|
159
|
+
else
|
160
|
+
nil # Return nil when no DESCRIPTION constant is defined
|
161
|
+
end
|
162
|
+
|
163
|
+
{
|
164
|
+
name: @name,
|
165
|
+
version: version,
|
166
|
+
description: description,
|
167
|
+
supported_formats: supported_formats,
|
168
|
+
class_name: self.class.name
|
169
|
+
}
|
170
|
+
end
|
171
|
+
|
172
|
+
# Alias for metadata (for test compatibility)
|
173
|
+
alias plugin_info metadata
|
174
|
+
|
175
|
+
private
|
176
|
+
|
177
|
+
# Validate metrics data structure
|
178
|
+
#
|
179
|
+
# @param metrics_data [Hash] Metrics data to validate
|
180
|
+
# @raise [ArgumentError] If data structure is invalid
|
181
|
+
def validate_metrics_data!(metrics_data)
|
182
|
+
raise ArgumentError, "Metrics data must be a Hash, got #{metrics_data.class}" unless metrics_data.is_a?(Hash)
|
183
|
+
|
184
|
+
raise ArgumentError, 'Metrics data must contain :metrics key' unless metrics_data.key?(:metrics)
|
185
|
+
|
186
|
+
return if metrics_data.key?(:timestamp)
|
187
|
+
|
188
|
+
raise ArgumentError, 'Metrics data must contain :timestamp key'
|
189
|
+
end
|
190
|
+
|
191
|
+
protected
|
192
|
+
|
193
|
+
# Structured logging helper for plugin events
|
194
|
+
#
|
195
|
+
# @param level [Symbol] Log level
|
196
|
+
# @param message [String] Log message
|
197
|
+
# @param context [Hash] Additional context
|
198
|
+
def log_plugin_event(level, message, **context)
|
199
|
+
# Safe class name extraction to avoid demodulize errors
|
200
|
+
class_name = self.class.name || 'AnonymousExporter'
|
201
|
+
|
202
|
+
log_structured(level, message,
|
203
|
+
entity_type: 'telemetry_plugin',
|
204
|
+
entity_id: @name,
|
205
|
+
plugin_name: @name,
|
206
|
+
plugin_version: @version,
|
207
|
+
plugin_class: class_name,
|
208
|
+
**context)
|
209
|
+
rescue StandardError => e
|
210
|
+
# Fallback logging if structured logging fails
|
211
|
+
Rails.logger.debug { "Structured logging failed: #{e.message}" }
|
212
|
+
Rails.logger.debug { "#{level.upcase}: #{message}" }
|
213
|
+
end
|
214
|
+
|
215
|
+
# Structured logging helper for plugin performance events
|
216
|
+
#
|
217
|
+
# @param operation [String] Operation name
|
218
|
+
# @param duration [Float] Duration in seconds
|
219
|
+
# @param context [Hash] Additional context
|
220
|
+
def log_plugin_performance(operation, duration, **context)
|
221
|
+
log_performance_event("plugin_#{operation}", duration,
|
222
|
+
entity_type: 'telemetry_plugin',
|
223
|
+
entity_id: @name,
|
224
|
+
plugin_name: @name,
|
225
|
+
plugin_version: @version,
|
226
|
+
**context)
|
227
|
+
end
|
228
|
+
|
229
|
+
# Structured logging helper for plugin errors
|
230
|
+
#
|
231
|
+
# @param exception [Exception] Exception to log
|
232
|
+
# @param context [Hash] Additional context
|
233
|
+
def log_plugin_exception(exception, **context)
|
234
|
+
log_exception(exception,
|
235
|
+
context: {
|
236
|
+
entity_type: 'telemetry_plugin',
|
237
|
+
entity_id: @name,
|
238
|
+
plugin_name: @name,
|
239
|
+
plugin_version: @version,
|
240
|
+
**context
|
241
|
+
})
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|