kaal 0.2.1 → 0.4.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 +4 -4
- data/README.md +79 -287
- data/Rakefile +4 -2
- data/config/kaal.rb +15 -0
- data/config/scheduler.yml +12 -0
- data/{lib/tasks/kaal_tasks.rake → exe/kaal} +5 -3
- data/lib/kaal/active_record_support.rb +82 -0
- data/lib/kaal/backend/adapter.rb +0 -1
- data/lib/kaal/backend/dispatch_attempt_logger.rb +33 -0
- data/lib/kaal/backend/dispatch_logging.rb +36 -23
- data/lib/kaal/backend/dispatch_registry_accessor.rb +43 -0
- data/lib/kaal/backend/memory_adapter.rb +7 -5
- data/lib/kaal/backend/mysql.rb +41 -0
- data/lib/kaal/backend/postgres.rb +41 -0
- data/lib/kaal/backend/redis_adapter.rb +6 -6
- data/lib/kaal/backend/sqlite.rb +41 -0
- data/lib/kaal/cli.rb +230 -0
- data/lib/kaal/{configuration.rb → config/configuration.rb} +0 -1
- data/lib/kaal/{scheduler_config_error.rb → config/scheduler_config_error.rb} +0 -1
- data/lib/kaal/config/scheduler_time_zone_resolver.rb +50 -0
- data/lib/kaal/config.rb +19 -0
- data/lib/kaal/{coordinator.rb → core/coordinator.rb} +42 -62
- data/lib/kaal/core/enabled_entry_enumerator.rb +51 -0
- data/lib/kaal/core/occurrence_finder.rb +38 -0
- data/lib/kaal/core.rb +18 -0
- data/lib/kaal/definition/database_engine.rb +54 -16
- data/lib/kaal/definition/memory_engine.rb +11 -18
- data/lib/kaal/definition/persistence_helpers.rb +31 -0
- data/lib/kaal/definition/redis_engine.rb +9 -6
- data/lib/kaal/definition/registry.rb +24 -2
- data/lib/kaal/definitions/registration_service.rb +62 -0
- data/lib/kaal/definitions/registry_accessor.rb +33 -0
- data/lib/kaal/dispatch/database_engine.rb +87 -61
- data/lib/kaal/dispatch/memory_engine.rb +3 -4
- data/lib/kaal/dispatch/redis_engine.rb +2 -3
- data/lib/kaal/dispatch/registry.rb +0 -1
- data/lib/kaal/internal/active_record/base_record.rb +16 -0
- data/lib/kaal/internal/active_record/connection_support.rb +96 -0
- data/lib/kaal/internal/active_record/database_backend.rb +73 -0
- data/lib/kaal/internal/active_record/definition_record.rb +16 -0
- data/lib/kaal/internal/active_record/definition_registry.rb +81 -0
- data/lib/kaal/internal/active_record/dispatch_record.rb +16 -0
- data/lib/kaal/internal/active_record/dispatch_registry.rb +100 -0
- data/lib/kaal/internal/active_record/lock_record.rb +16 -0
- data/lib/kaal/internal/active_record/migration_templates.rb +108 -0
- data/lib/kaal/internal/active_record/mysql_backend.rb +71 -0
- data/lib/kaal/internal/active_record/postgres_backend.rb +69 -0
- data/lib/kaal/internal/active_record.rb +17 -0
- data/lib/kaal/internal/sequel/database_backend.rb +74 -0
- data/lib/kaal/internal/sequel/mysql_backend.rb +69 -0
- data/lib/kaal/internal/sequel/postgres_backend.rb +67 -0
- data/lib/kaal/internal/sequel.rb +12 -0
- data/lib/kaal/persistence/database.rb +35 -0
- data/lib/kaal/persistence/migration_templates.rb +97 -0
- data/lib/kaal/register_conflict_support.rb +0 -1
- data/lib/kaal/registry.rb +0 -3
- data/lib/kaal/runtime/runtime_context.rb +41 -0
- data/lib/kaal/runtime/scheduler_boot_loader.rb +52 -0
- data/lib/kaal/runtime/signal_handler_chain.rb +42 -0
- data/lib/kaal/runtime/signal_handler_installer.rb +39 -0
- data/lib/kaal/runtime.rb +20 -0
- data/lib/kaal/scheduler_file/hash_transform.rb +22 -0
- data/lib/kaal/scheduler_file/helper_bundle.rb +28 -0
- data/lib/kaal/scheduler_file/job_applier.rb +242 -0
- data/lib/kaal/scheduler_file/job_normalizer.rb +90 -0
- data/lib/kaal/scheduler_file/loader.rb +152 -0
- data/lib/kaal/scheduler_file/payload_loader.rb +95 -0
- data/lib/kaal/{scheduler_placeholder_support.rb → scheduler_file/placeholder_support.rb} +0 -1
- data/lib/kaal/scheduler_file.rb +18 -0
- data/lib/kaal/sequel_support.rb +82 -0
- data/lib/kaal/support/hash_tools.rb +93 -0
- data/lib/kaal/{cron_humanizer.rb → utils/cron_humanizer.rb} +19 -1
- data/lib/kaal/{cron_utils.rb → utils/cron_utils.rb} +0 -1
- data/lib/kaal/{idempotency_key_generator.rb → utils/idempotency_key_generator.rb} +3 -3
- data/lib/kaal/utils.rb +18 -0
- data/lib/kaal/version.rb +1 -2
- data/lib/kaal.rb +83 -397
- metadata +87 -42
- data/app/models/kaal/cron_definition.rb +0 -76
- data/app/models/kaal/cron_dispatch.rb +0 -50
- data/app/models/kaal/cron_lock.rb +0 -38
- data/lib/generators/kaal/install/install_generator.rb +0 -72
- data/lib/generators/kaal/install/templates/create_kaal_definitions.rb.tt +0 -21
- data/lib/generators/kaal/install/templates/create_kaal_dispatches.rb.tt +0 -20
- data/lib/generators/kaal/install/templates/create_kaal_locks.rb.tt +0 -17
- data/lib/generators/kaal/install/templates/kaal.rb.tt +0 -31
- data/lib/generators/kaal/install/templates/scheduler.yml.tt +0 -22
- data/lib/kaal/backend/mysql_adapter.rb +0 -170
- data/lib/kaal/backend/postgres_adapter.rb +0 -134
- data/lib/kaal/backend/sqlite_adapter.rb +0 -116
- data/lib/kaal/railtie.rb +0 -183
- data/lib/kaal/rake_tasks.rb +0 -184
- data/lib/kaal/scheduler_file_loader.rb +0 -321
- data/lib/kaal/scheduler_hash_transform.rb +0 -45
metadata
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kaal
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.4.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nitesh Purohit
|
|
8
|
-
|
|
8
|
+
- Codevedas Inc.
|
|
9
|
+
bindir: exe
|
|
9
10
|
cert_chain: []
|
|
10
11
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
12
|
dependencies:
|
|
@@ -24,91 +25,135 @@ dependencies:
|
|
|
24
25
|
- !ruby/object:Gem::Version
|
|
25
26
|
version: '1.8'
|
|
26
27
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
28
|
+
name: i18n
|
|
28
29
|
requirement: !ruby/object:Gem::Requirement
|
|
29
30
|
requirements:
|
|
30
|
-
- - "
|
|
31
|
-
- !ruby/object:Gem::Version
|
|
32
|
-
version: '7.1'
|
|
33
|
-
- - "<"
|
|
31
|
+
- - "~>"
|
|
34
32
|
- !ruby/object:Gem::Version
|
|
35
|
-
version: '
|
|
33
|
+
version: '1.14'
|
|
36
34
|
type: :runtime
|
|
37
35
|
prerelease: false
|
|
38
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
39
37
|
requirements:
|
|
40
|
-
- - "
|
|
38
|
+
- - "~>"
|
|
41
39
|
- !ruby/object:Gem::Version
|
|
42
|
-
version: '
|
|
43
|
-
|
|
40
|
+
version: '1.14'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: thor
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - "~>"
|
|
44
46
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: '
|
|
47
|
+
version: '1.3'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - "~>"
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '1.3'
|
|
46
55
|
- !ruby/object:Gem::Dependency
|
|
47
|
-
name:
|
|
56
|
+
name: tzinfo
|
|
48
57
|
requirement: !ruby/object:Gem::Requirement
|
|
49
58
|
requirements:
|
|
50
|
-
- - "
|
|
59
|
+
- - "~>"
|
|
51
60
|
- !ruby/object:Gem::Version
|
|
52
|
-
version: '
|
|
61
|
+
version: '2.0'
|
|
53
62
|
type: :runtime
|
|
54
63
|
prerelease: false
|
|
55
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
56
65
|
requirements:
|
|
57
|
-
- - "
|
|
66
|
+
- - "~>"
|
|
58
67
|
- !ruby/object:Gem::Version
|
|
59
|
-
version: '
|
|
68
|
+
version: '2.0'
|
|
60
69
|
description: " Kaal is a distributed cron scheduler for Ruby that safely executes
|
|
61
70
|
scheduled tasks across multiple nodes.\n"
|
|
62
71
|
email:
|
|
63
72
|
- nitesh.purohit.it@gmail.com
|
|
64
|
-
|
|
73
|
+
- team@codevedas.com
|
|
74
|
+
executables:
|
|
75
|
+
- kaal
|
|
65
76
|
extensions: []
|
|
66
77
|
extra_rdoc_files: []
|
|
67
78
|
files:
|
|
68
79
|
- LICENSE
|
|
69
80
|
- README.md
|
|
70
81
|
- Rakefile
|
|
71
|
-
-
|
|
72
|
-
- app/models/kaal/cron_dispatch.rb
|
|
73
|
-
- app/models/kaal/cron_lock.rb
|
|
82
|
+
- config/kaal.rb
|
|
74
83
|
- config/locales/en.yml
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
- lib/generators/kaal/install/templates/create_kaal_dispatches.rb.tt
|
|
78
|
-
- lib/generators/kaal/install/templates/create_kaal_locks.rb.tt
|
|
79
|
-
- lib/generators/kaal/install/templates/kaal.rb.tt
|
|
80
|
-
- lib/generators/kaal/install/templates/scheduler.yml.tt
|
|
84
|
+
- config/scheduler.yml
|
|
85
|
+
- exe/kaal
|
|
81
86
|
- lib/kaal.rb
|
|
87
|
+
- lib/kaal/active_record_support.rb
|
|
82
88
|
- lib/kaal/backend/adapter.rb
|
|
89
|
+
- lib/kaal/backend/dispatch_attempt_logger.rb
|
|
83
90
|
- lib/kaal/backend/dispatch_logging.rb
|
|
91
|
+
- lib/kaal/backend/dispatch_registry_accessor.rb
|
|
84
92
|
- lib/kaal/backend/memory_adapter.rb
|
|
85
|
-
- lib/kaal/backend/
|
|
86
|
-
- lib/kaal/backend/
|
|
93
|
+
- lib/kaal/backend/mysql.rb
|
|
94
|
+
- lib/kaal/backend/postgres.rb
|
|
87
95
|
- lib/kaal/backend/redis_adapter.rb
|
|
88
|
-
- lib/kaal/backend/
|
|
89
|
-
- lib/kaal/
|
|
90
|
-
- lib/kaal/
|
|
91
|
-
- lib/kaal/
|
|
92
|
-
- lib/kaal/
|
|
96
|
+
- lib/kaal/backend/sqlite.rb
|
|
97
|
+
- lib/kaal/cli.rb
|
|
98
|
+
- lib/kaal/config.rb
|
|
99
|
+
- lib/kaal/config/configuration.rb
|
|
100
|
+
- lib/kaal/config/scheduler_config_error.rb
|
|
101
|
+
- lib/kaal/config/scheduler_time_zone_resolver.rb
|
|
102
|
+
- lib/kaal/core.rb
|
|
103
|
+
- lib/kaal/core/coordinator.rb
|
|
104
|
+
- lib/kaal/core/enabled_entry_enumerator.rb
|
|
105
|
+
- lib/kaal/core/occurrence_finder.rb
|
|
93
106
|
- lib/kaal/definition/database_engine.rb
|
|
94
107
|
- lib/kaal/definition/memory_engine.rb
|
|
108
|
+
- lib/kaal/definition/persistence_helpers.rb
|
|
95
109
|
- lib/kaal/definition/redis_engine.rb
|
|
96
110
|
- lib/kaal/definition/registry.rb
|
|
111
|
+
- lib/kaal/definitions/registration_service.rb
|
|
112
|
+
- lib/kaal/definitions/registry_accessor.rb
|
|
97
113
|
- lib/kaal/dispatch/database_engine.rb
|
|
98
114
|
- lib/kaal/dispatch/memory_engine.rb
|
|
99
115
|
- lib/kaal/dispatch/redis_engine.rb
|
|
100
116
|
- lib/kaal/dispatch/registry.rb
|
|
101
|
-
- lib/kaal/
|
|
102
|
-
- lib/kaal/
|
|
103
|
-
- lib/kaal/
|
|
117
|
+
- lib/kaal/internal/active_record.rb
|
|
118
|
+
- lib/kaal/internal/active_record/base_record.rb
|
|
119
|
+
- lib/kaal/internal/active_record/connection_support.rb
|
|
120
|
+
- lib/kaal/internal/active_record/database_backend.rb
|
|
121
|
+
- lib/kaal/internal/active_record/definition_record.rb
|
|
122
|
+
- lib/kaal/internal/active_record/definition_registry.rb
|
|
123
|
+
- lib/kaal/internal/active_record/dispatch_record.rb
|
|
124
|
+
- lib/kaal/internal/active_record/dispatch_registry.rb
|
|
125
|
+
- lib/kaal/internal/active_record/lock_record.rb
|
|
126
|
+
- lib/kaal/internal/active_record/migration_templates.rb
|
|
127
|
+
- lib/kaal/internal/active_record/mysql_backend.rb
|
|
128
|
+
- lib/kaal/internal/active_record/postgres_backend.rb
|
|
129
|
+
- lib/kaal/internal/sequel.rb
|
|
130
|
+
- lib/kaal/internal/sequel/database_backend.rb
|
|
131
|
+
- lib/kaal/internal/sequel/mysql_backend.rb
|
|
132
|
+
- lib/kaal/internal/sequel/postgres_backend.rb
|
|
133
|
+
- lib/kaal/persistence/database.rb
|
|
134
|
+
- lib/kaal/persistence/migration_templates.rb
|
|
104
135
|
- lib/kaal/register_conflict_support.rb
|
|
105
136
|
- lib/kaal/registry.rb
|
|
106
|
-
- lib/kaal/
|
|
107
|
-
- lib/kaal/
|
|
108
|
-
- lib/kaal/
|
|
109
|
-
- lib/kaal/
|
|
137
|
+
- lib/kaal/runtime.rb
|
|
138
|
+
- lib/kaal/runtime/runtime_context.rb
|
|
139
|
+
- lib/kaal/runtime/scheduler_boot_loader.rb
|
|
140
|
+
- lib/kaal/runtime/signal_handler_chain.rb
|
|
141
|
+
- lib/kaal/runtime/signal_handler_installer.rb
|
|
142
|
+
- lib/kaal/scheduler_file.rb
|
|
143
|
+
- lib/kaal/scheduler_file/hash_transform.rb
|
|
144
|
+
- lib/kaal/scheduler_file/helper_bundle.rb
|
|
145
|
+
- lib/kaal/scheduler_file/job_applier.rb
|
|
146
|
+
- lib/kaal/scheduler_file/job_normalizer.rb
|
|
147
|
+
- lib/kaal/scheduler_file/loader.rb
|
|
148
|
+
- lib/kaal/scheduler_file/payload_loader.rb
|
|
149
|
+
- lib/kaal/scheduler_file/placeholder_support.rb
|
|
150
|
+
- lib/kaal/sequel_support.rb
|
|
151
|
+
- lib/kaal/support/hash_tools.rb
|
|
152
|
+
- lib/kaal/utils.rb
|
|
153
|
+
- lib/kaal/utils/cron_humanizer.rb
|
|
154
|
+
- lib/kaal/utils/cron_utils.rb
|
|
155
|
+
- lib/kaal/utils/idempotency_key_generator.rb
|
|
110
156
|
- lib/kaal/version.rb
|
|
111
|
-
- lib/tasks/kaal_tasks.rake
|
|
112
157
|
homepage: https://github.com/Code-Vedas/kaal
|
|
113
158
|
licenses:
|
|
114
159
|
- MIT
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright Codevedas Inc. 2025-present
|
|
4
|
-
#
|
|
5
|
-
# This source code is licensed under the MIT license found in the
|
|
6
|
-
# LICENSE file in the root directory of this source tree.
|
|
7
|
-
|
|
8
|
-
module Kaal
|
|
9
|
-
# Persistent scheduler definition model.
|
|
10
|
-
class CronDefinition < ApplicationRecord
|
|
11
|
-
self.table_name = 'kaal_definitions'
|
|
12
|
-
|
|
13
|
-
before_validation :ensure_metadata
|
|
14
|
-
|
|
15
|
-
validates :key, presence: true, uniqueness: true
|
|
16
|
-
validates :cron, presence: true
|
|
17
|
-
validates :source, presence: true
|
|
18
|
-
validates :enabled, inclusion: { in: [true, false] }
|
|
19
|
-
|
|
20
|
-
scope :enabled, -> { where(enabled: true) }
|
|
21
|
-
scope :disabled, -> { where(enabled: false) }
|
|
22
|
-
scope :by_source, ->(source) { where(source: source) }
|
|
23
|
-
|
|
24
|
-
def self.upsert_definition!(key:, cron:, enabled:, source:, metadata:)
|
|
25
|
-
persist_definition(find_or_initialize_by(key: key), cron:, enabled:, source:, metadata:)
|
|
26
|
-
rescue ActiveRecord::RecordNotUnique
|
|
27
|
-
persist_definition(find_by!(key: key), cron:, enabled:, source:, metadata:)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def to_definition_hash
|
|
31
|
-
{
|
|
32
|
-
key: key,
|
|
33
|
-
cron: cron,
|
|
34
|
-
enabled: enabled,
|
|
35
|
-
source: source,
|
|
36
|
-
metadata: metadata || {},
|
|
37
|
-
created_at: created_at,
|
|
38
|
-
updated_at: updated_at,
|
|
39
|
-
disabled_at: disabled_at
|
|
40
|
-
}
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def destroy_and_return_definition_hash
|
|
44
|
-
definition_hash = to_definition_hash
|
|
45
|
-
destroy!
|
|
46
|
-
definition_hash
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def self.persist_definition(record, cron:, enabled:, source:, metadata:)
|
|
50
|
-
disabled_at = if enabled
|
|
51
|
-
nil
|
|
52
|
-
elsif record.new_record? || record.enabled != false
|
|
53
|
-
Time.current
|
|
54
|
-
else
|
|
55
|
-
record.disabled_at
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
record.assign_attributes(
|
|
59
|
-
cron: cron,
|
|
60
|
-
enabled: enabled,
|
|
61
|
-
source: source,
|
|
62
|
-
metadata: metadata,
|
|
63
|
-
disabled_at:
|
|
64
|
-
)
|
|
65
|
-
record.save!
|
|
66
|
-
record
|
|
67
|
-
end
|
|
68
|
-
private_class_method :persist_definition
|
|
69
|
-
|
|
70
|
-
private
|
|
71
|
-
|
|
72
|
-
def ensure_metadata
|
|
73
|
-
self.metadata ||= {}
|
|
74
|
-
end
|
|
75
|
-
end
|
|
76
|
-
end
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright Codevedas Inc. 2025-present
|
|
4
|
-
#
|
|
5
|
-
# This source code is licensed under the MIT license found in the
|
|
6
|
-
# LICENSE file in the root directory of this source tree.
|
|
7
|
-
|
|
8
|
-
module Kaal
|
|
9
|
-
##
|
|
10
|
-
# Audit model for tracking cron job dispatch attempts across the cluster.
|
|
11
|
-
#
|
|
12
|
-
# CronDispatch records information about each cron job that was dispatched,
|
|
13
|
-
# including the cron key, scheduled fire time, actual dispatch time,
|
|
14
|
-
# the node that dispatched it, and the dispatch status.
|
|
15
|
-
#
|
|
16
|
-
# This model is used by the PostgreSQL lock adapter for observability and
|
|
17
|
-
# debugging in distributed deployments. You can use this table to:
|
|
18
|
-
# - Verify that jobs are only dispatched once per fire_time
|
|
19
|
-
# - Track which node dispatched each job
|
|
20
|
-
# - Monitor dispatch latency
|
|
21
|
-
# - Audit job execution history
|
|
22
|
-
#
|
|
23
|
-
# @example Query dispatch history
|
|
24
|
-
# Kaal::CronDispatch.where(
|
|
25
|
-
# key: 'send_emails',
|
|
26
|
-
# status: 'dispatched'
|
|
27
|
-
# ).order(fire_time: :desc).limit(10)
|
|
28
|
-
#
|
|
29
|
-
# @example Find all dispatches from a specific node
|
|
30
|
-
# Kaal::CronDispatch.where(node_id: 'worker1').order(dispatched_at: :desc)
|
|
31
|
-
class CronDispatch < ApplicationRecord
|
|
32
|
-
self.table_name = 'kaal_dispatches'
|
|
33
|
-
|
|
34
|
-
##
|
|
35
|
-
# Validations
|
|
36
|
-
validates :key, presence: true
|
|
37
|
-
validates :fire_time, presence: true
|
|
38
|
-
validates :dispatched_at, presence: true
|
|
39
|
-
validates :node_id, presence: true
|
|
40
|
-
validates :status, presence: true, inclusion: { in: %w[dispatched failed] }
|
|
41
|
-
|
|
42
|
-
##
|
|
43
|
-
# Scopes for common queries
|
|
44
|
-
scope :recent, ->(limit = 100) { order(dispatched_at: :desc).limit(limit) }
|
|
45
|
-
scope :by_key, ->(key) { where(key: key) }
|
|
46
|
-
scope :by_node, ->(node_id) { where(node_id: node_id) }
|
|
47
|
-
scope :by_status, ->(status) { where(status: status) }
|
|
48
|
-
scope :since, ->(timestamp) { where('dispatched_at >= ?', timestamp) }
|
|
49
|
-
end
|
|
50
|
-
end
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright Codevedas Inc. 2025-present
|
|
4
|
-
#
|
|
5
|
-
# This source code is licensed under the MIT license found in the
|
|
6
|
-
# LICENSE file in the root directory of this source tree.
|
|
7
|
-
|
|
8
|
-
module Kaal
|
|
9
|
-
##
|
|
10
|
-
# Model for distributed lock records (database-backed).
|
|
11
|
-
#
|
|
12
|
-
# Used by the database-backed adapter (SQLiteAdapter) to store lock state in a database table.
|
|
13
|
-
# Works with any ActiveRecord-supported SQL database (SQLite, PostgreSQL, MySQL, etc.).
|
|
14
|
-
# Each row represents a held lock with an expiration time.
|
|
15
|
-
class CronLock < ApplicationRecord
|
|
16
|
-
self.table_name = 'kaal_locks'
|
|
17
|
-
|
|
18
|
-
validates :key, presence: true, uniqueness: true
|
|
19
|
-
validates :acquired_at, presence: true
|
|
20
|
-
validates :expires_at, presence: true
|
|
21
|
-
|
|
22
|
-
##
|
|
23
|
-
# Find and delete any expired locks (cleanup).
|
|
24
|
-
#
|
|
25
|
-
# @return [Integer] number of locks deleted
|
|
26
|
-
def self.cleanup_expired
|
|
27
|
-
where('expires_at < ?', Time.current).delete_all
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
##
|
|
31
|
-
# Check if this lock is still valid (not expired).
|
|
32
|
-
#
|
|
33
|
-
# @return [Boolean] true if not expired
|
|
34
|
-
def not_expired?
|
|
35
|
-
expires_at > Time.current
|
|
36
|
-
end
|
|
37
|
-
end
|
|
38
|
-
end
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Copyright Codevedas Inc. 2025-present
|
|
4
|
-
#
|
|
5
|
-
# This source code is licensed under the MIT license found in the
|
|
6
|
-
# LICENSE file in the root directory of this source tree.
|
|
7
|
-
|
|
8
|
-
require 'rails/generators'
|
|
9
|
-
require 'rails/generators/active_record'
|
|
10
|
-
|
|
11
|
-
module Kaal
|
|
12
|
-
module Generators
|
|
13
|
-
# Installs the database migrations needed for the selected backend.
|
|
14
|
-
class InstallGenerator < Rails::Generators::Base
|
|
15
|
-
include Rails::Generators::Migration
|
|
16
|
-
|
|
17
|
-
source_root File.expand_path('templates', __dir__)
|
|
18
|
-
|
|
19
|
-
class_option :backend,
|
|
20
|
-
type: :string,
|
|
21
|
-
default: 'sqlite',
|
|
22
|
-
desc: 'Backend to install migrations for: sqlite, postgres, mysql, redis, memory'
|
|
23
|
-
|
|
24
|
-
def create_initializer
|
|
25
|
-
template 'kaal.rb.tt', 'config/initializers/kaal.rb'
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def create_scheduler_config
|
|
29
|
-
template 'scheduler.yml.tt', 'config/scheduler.yml'
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def install_migrations
|
|
33
|
-
templates = migration_templates
|
|
34
|
-
return say_status(:skip, "No database migrations required for #{normalized_backend} backend", :yellow) if templates.empty?
|
|
35
|
-
|
|
36
|
-
templates.each do |template_name|
|
|
37
|
-
migration_template "#{template_name}.rb.tt", "db/migrate/#{template_name}.rb"
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
def self.next_migration_number(dirname)
|
|
42
|
-
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
def migration_templates
|
|
48
|
-
case normalized_backend
|
|
49
|
-
when 'sqlite', 'database'
|
|
50
|
-
%w[
|
|
51
|
-
create_kaal_dispatches
|
|
52
|
-
create_kaal_locks
|
|
53
|
-
create_kaal_definitions
|
|
54
|
-
]
|
|
55
|
-
when 'postgres', 'mysql'
|
|
56
|
-
%w[
|
|
57
|
-
create_kaal_dispatches
|
|
58
|
-
create_kaal_definitions
|
|
59
|
-
]
|
|
60
|
-
when 'memory', 'redis'
|
|
61
|
-
[]
|
|
62
|
-
else
|
|
63
|
-
raise Thor::Error, "Unsupported backend '#{options['backend']}'. Use sqlite, postgres, mysql, redis, or memory."
|
|
64
|
-
end
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
def normalized_backend
|
|
68
|
-
options['backend'].to_s.downcase
|
|
69
|
-
end
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
end
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Creates the persisted cron definitions table for database-backed definitions.
|
|
4
|
-
class CreateKaalDefinitions < ActiveRecord::Migration[7.0]
|
|
5
|
-
def change
|
|
6
|
-
create_table :kaal_definitions do |t|
|
|
7
|
-
t.string :key, null: false, limit: 255
|
|
8
|
-
t.string :cron, null: false, limit: 255
|
|
9
|
-
t.boolean :enabled, null: false, default: true
|
|
10
|
-
t.string :source, null: false, limit: 50, default: 'code'
|
|
11
|
-
t.json :metadata, null: false
|
|
12
|
-
t.datetime :disabled_at
|
|
13
|
-
|
|
14
|
-
t.timestamps
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
add_index :kaal_definitions, :key, unique: true
|
|
18
|
-
add_index :kaal_definitions, :enabled
|
|
19
|
-
add_index :kaal_definitions, :source
|
|
20
|
-
end
|
|
21
|
-
end
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Creates the dispatch records table for database-backed dispatch logging.
|
|
4
|
-
class CreateKaalDispatches < ActiveRecord::Migration[7.0]
|
|
5
|
-
def change
|
|
6
|
-
create_table :kaal_dispatches do |t|
|
|
7
|
-
t.string :key, null: false, limit: 255
|
|
8
|
-
t.datetime :fire_time, null: false
|
|
9
|
-
t.datetime :dispatched_at, null: false
|
|
10
|
-
t.string :node_id, null: false, limit: 255
|
|
11
|
-
t.string :status, null: false, limit: 50, default: 'dispatched'
|
|
12
|
-
|
|
13
|
-
t.timestamps
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
add_index :kaal_dispatches, %i[key fire_time], unique: true
|
|
17
|
-
add_index :kaal_dispatches, :dispatched_at
|
|
18
|
-
add_index :kaal_dispatches, :status
|
|
19
|
-
end
|
|
20
|
-
end
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Creates the lock table for database-backed lease coordination.
|
|
4
|
-
class CreateKaalLocks < ActiveRecord::Migration[7.0]
|
|
5
|
-
def change
|
|
6
|
-
create_table :kaal_locks do |t|
|
|
7
|
-
t.string :key, null: false, limit: 255
|
|
8
|
-
t.datetime :acquired_at, null: false
|
|
9
|
-
t.datetime :expires_at, null: false
|
|
10
|
-
|
|
11
|
-
t.timestamps
|
|
12
|
-
end
|
|
13
|
-
|
|
14
|
-
add_index :kaal_locks, :key, unique: true
|
|
15
|
-
add_index :kaal_locks, :expires_at
|
|
16
|
-
end
|
|
17
|
-
end
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
Kaal.configure do |config|
|
|
4
|
-
# Select the backend that matches your deployment.
|
|
5
|
-
# See the Kaal documentation for backend-specific setup and the full
|
|
6
|
-
# configuration reference.
|
|
7
|
-
#
|
|
8
|
-
# Redis (recommended for multi-node deployments):
|
|
9
|
-
# config.backend = Kaal::Backend::RedisAdapter.new(Redis.new(url: ENV.fetch('REDIS_URL')))
|
|
10
|
-
#
|
|
11
|
-
# PostgreSQL advisory locks:
|
|
12
|
-
# config.backend = Kaal::Backend::PostgresAdapter.new
|
|
13
|
-
#
|
|
14
|
-
# MySQL / SQLite database-backed coordination:
|
|
15
|
-
# config.backend = Kaal::Backend::SQLiteAdapter.new
|
|
16
|
-
|
|
17
|
-
config.tick_interval = 5
|
|
18
|
-
config.window_lookback = 120
|
|
19
|
-
# Keep lease_ttl >= window_lookback + tick_interval to prevent duplicate dispatch.
|
|
20
|
-
config.lease_ttl = 125
|
|
21
|
-
config.recovery_window = 3600
|
|
22
|
-
config.enable_dispatch_recovery = true
|
|
23
|
-
config.enable_log_dispatch_registry = false
|
|
24
|
-
|
|
25
|
-
# Scheduler file loading
|
|
26
|
-
config.scheduler_config_path = 'config/scheduler.yml'
|
|
27
|
-
# :error, :code_wins, :file_wins
|
|
28
|
-
config.scheduler_conflict_policy = :error
|
|
29
|
-
# :warn, :error
|
|
30
|
-
config.scheduler_missing_file_policy = :warn
|
|
31
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
defaults:
|
|
2
|
-
jobs:
|
|
3
|
-
- key: "reports:weekly_summary"
|
|
4
|
-
cron: "0 9 * * 1"
|
|
5
|
-
job_class: "WeeklySummaryJob"
|
|
6
|
-
enabled: true
|
|
7
|
-
queue: "default"
|
|
8
|
-
args:
|
|
9
|
-
- "{{fire_time.iso8601}}"
|
|
10
|
-
kwargs:
|
|
11
|
-
idempotency_key: "{{idempotency_key}}"
|
|
12
|
-
metadata:
|
|
13
|
-
owner: "ops"
|
|
14
|
-
|
|
15
|
-
development:
|
|
16
|
-
jobs: []
|
|
17
|
-
|
|
18
|
-
test:
|
|
19
|
-
jobs: []
|
|
20
|
-
|
|
21
|
-
production:
|
|
22
|
-
jobs: []
|