legion-data 1.10.28 → 1.11.7

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.
@@ -2,7 +2,6 @@
2
2
 
3
3
  require 'legion/logging/helper'
4
4
  require 'legion/data/auth_failure_handler'
5
- require 'legion/data/connection_pool'
6
5
 
7
6
  require 'fileutils'
8
7
  require 'sequel'
@@ -166,52 +165,43 @@ module Legion
166
165
  class << self
167
166
  include Legion::Logging::Helper
168
167
 
169
- attr_reader :sequel
170
-
171
- def sequel=(database)
172
- if database
173
- pool = database.pool
174
- pool.extend(Legion::Data::ConnectionPool) unless pool.is_a?(Legion::Data::ConnectionPool)
175
- end
176
- Legion::Data.reset_privileges!
177
- @sequel = database
178
- end
168
+ attr_accessor :sequel
179
169
 
180
170
  def adapter
181
- @adapter ||= Legion::Settings[:data][:adapter]&.to_sym || :sqlite
171
+ @adapter || Legion::Settings[:data][:adapter].to_sym
182
172
  end
183
173
 
184
174
  def setup
185
175
  Legion::Settings[:data][:connected] = false
186
176
  @sequel&.disconnect
187
177
  @sequel = nil
188
- @adapter = Legion::Settings[:data][:adapter]&.to_sym || :sqlite
178
+ @adapter = Legion::Settings[:data][:adapter].to_sym
189
179
  opts = sequel_opts
190
180
  log.info("Legion::Data::Connection setup adapter=#{adapter}")
191
181
  @fallback_active = false
192
182
  @replica_servers = []
193
- self.sequel = if adapter == :sqlite
194
- ::Sequel.connect(opts.merge(adapter: :sqlite, database: sqlite_path))
195
- else
196
- attempted_adapter = adapter
197
- begin
198
- ::Sequel.connect(connection_opts_for(adapter: attempted_adapter, opts: opts))
199
- rescue UnresolvedCredentialError => e
200
- handle_exception(e, level: :fatal, handled: false, operation: :data_connect)
201
- raise
202
- rescue ::Sequel::DatabaseConnectionError => e
203
- raise unless dev_fallback?
204
-
205
- log.error("Legion::Data FALLING BACK TO SQLITE — #{attempted_adapter} network DB connection failed: #{e.message}")
206
- log.error("Legion::Data WARNING: Data written to SQLite will NOT be visible when #{attempted_adapter} reconnects. " \
207
- 'Apollo knowledge, audit logs, and other DB-backed services will use a local-only store.')
208
- handle_exception(e, level: :error, handled: true, operation: :shared_connect, fallback: :sqlite)
209
- @adapter = :sqlite
210
- @fallback_active = true
211
- sqlite_opts = sequel_opts
212
- ::Sequel.connect(sqlite_opts.merge(adapter: :sqlite, database: sqlite_path))
213
- end
214
- end
183
+ @sequel = if adapter == :sqlite
184
+ ::Sequel.connect(opts.merge(adapter: :sqlite, database: sqlite_path))
185
+ else
186
+ attempted_adapter = adapter
187
+ begin
188
+ ::Sequel.connect(connection_opts_for(adapter: attempted_adapter, opts: opts))
189
+ rescue UnresolvedCredentialError => e
190
+ handle_exception(e, level: :fatal, handled: false, operation: :data_connect)
191
+ raise
192
+ rescue StandardError => e
193
+ raise unless dev_fallback?
194
+
195
+ log.error("Legion::Data FALLING BACK TO SQLITE — #{attempted_adapter} network DB connection failed: #{e.message}")
196
+ log.error("Legion::Data WARNING: Data written to SQLite will NOT be visible when #{attempted_adapter} reconnects. " \
197
+ 'Apollo knowledge, audit logs, and other DB-backed services will use a local-only store.')
198
+ handle_exception(e, level: :error, handled: true, operation: :shared_connect, fallback: :sqlite)
199
+ @adapter = :sqlite
200
+ @fallback_active = true
201
+ sqlite_opts = sequel_opts
202
+ ::Sequel.connect(sqlite_opts.merge(adapter: :sqlite, database: sqlite_path))
203
+ end
204
+ end
215
205
  @replica_servers = @sequel.opts.fetch(:servers, {}).keys
216
206
  log_connection_info
217
207
  configure_extensions
@@ -230,8 +220,7 @@ module Legion
230
220
  adapter: adapter,
231
221
  connected: Legion::Settings[:data][:connected],
232
222
  fallback_active: @fallback_active || false,
233
- configured_adapter: Legion::Settings[:data][:adapter]&.to_sym || :sqlite,
234
- shutdown: @sequel&.pool&.shutdown_status,
223
+ configured_adapter: Legion::Settings[:data][:adapter].to_sym,
235
224
  sequel_alive: (begin
236
225
  !@sequel&.test_connection.nil?
237
226
  rescue StandardError => e
@@ -298,26 +287,14 @@ module Legion
298
287
  end
299
288
 
300
289
  def shutdown
301
- database = @sequel
302
- logger = @query_file_logger
303
- on_closed = proc do
304
- logger&.close
305
- if @sequel.equal?(database)
306
- @query_file_logger = nil
307
- @fallback_active = false
308
- @replica_servers = []
309
- Legion::Settings[:data][:connected] = false
310
- end
311
- log.info 'Legion::Data connection closed'
312
- end
313
- unless database
314
- on_closed.call
315
- return true
316
- end
317
-
318
- closed = database.pool.shutdown(timeout: Legion::Settings[:data][:shutdown_timeout], &on_closed)
319
- log.warn("Legion::Data shutdown incomplete: #{database.pool.shutdown_status}") unless closed
320
- closed
290
+ @sequel&.disconnect
291
+ @query_file_logger&.close
292
+ @query_file_logger = nil
293
+ @fallback_active = false
294
+ @replica_servers = []
295
+ Legion::Settings[:data][:connected] = false
296
+ log.info 'Legion::Data connection closed'
297
+ true
321
298
  end
322
299
 
323
300
  def reconnect_with_fresh_creds
@@ -376,7 +353,7 @@ module Legion
376
353
  return creds if adapter == :sqlite
377
354
  return creds unless defined?(Legion::Crypt::TLS)
378
355
 
379
- tls_settings = data_tls_settings
356
+ tls_settings = Legion::Settings[:data][:tls]
380
357
  return creds unless tls_settings[:enabled] == true
381
358
 
382
359
  tls = Legion::Crypt::TLS.resolve(tls_settings, port: port)
@@ -424,15 +401,6 @@ module Legion
424
401
 
425
402
  private
426
403
 
427
- def data_tls_settings
428
- return {} unless defined?(Legion::Settings)
429
-
430
- Legion::Settings[:data][:tls] || {}
431
- rescue StandardError => e
432
- handle_exception(e, level: :warn, handled: true, operation: :data_tls_settings)
433
- {}
434
- end
435
-
436
404
  def log_connection_info
437
405
  if adapter == :sqlite
438
406
  log.info "Connected to SQLite at #{sqlite_path}"
@@ -464,7 +432,7 @@ module Legion
464
432
  end
465
433
 
466
434
  def sqlite_path
467
- path = Legion::Settings[:data][:creds][:database] || 'legionio.db'
435
+ path = Legion::Settings[:data][:creds][:database]
468
436
  return path if File.absolute_path?(path)
469
437
 
470
438
  base_dir = File.expand_path('~/.legionio/data')
@@ -610,7 +578,7 @@ module Legion
610
578
  stats[pragma.to_sym] = val unless val.nil?
611
579
  end
612
580
 
613
- db_path = Legion::Settings[:data][:creds][:database] || 'legionio.db'
581
+ db_path = Legion::Settings[:data][:creds][:database]
614
582
  stats[:file_size] = File.size(db_path) if File.exist?(db_path)
615
583
  stats[:database_size_bytes] = (stats[:page_size].to_i * stats[:page_count].to_i) if stats[:page_size] && stats[:page_count]
616
584
  stats
@@ -698,15 +666,14 @@ module Legion
698
666
 
699
667
  install_auth_failure_hook
700
668
  rescue StandardError => e
701
- handle_exception(e, level: :error, handled: false, operation: :configure_extensions, adapter: adapter)
702
- raise
669
+ handle_exception(e, level: :warn, handled: true, operation: :configure_extensions, adapter: adapter)
670
+ raise e
703
671
  end
704
672
 
705
673
  def install_auth_failure_hook
706
674
  Legion::Data::AuthFailureHandler.install(@sequel)
707
675
  rescue StandardError => e
708
- handle_exception(e, level: :error, handled: false, operation: :install_auth_failure_hook)
709
- raise
676
+ handle_exception(e, level: :warn, handled: true, operation: :install_auth_failure_hook)
710
677
  end
711
678
 
712
679
  def build_data_logger
@@ -3,11 +3,12 @@
3
3
  module Legion
4
4
  module Data
5
5
  module DatabaseLock
6
- def self.with_claim(database:, table:, key:)
6
+ def self.with_claim(key:)
7
+ database = Legion::Data::Model::AppendClaim.db
7
8
  options = { savepoint: true }
8
9
  options[:mode] = :immediate if database.database_type == :sqlite
9
10
  database.transaction(**options) do
10
- claim = database[table].where(key)
11
+ claim = Legion::Data::Model::AppendClaim.where(key)
11
12
  # InnoDB needs exclusive duplicate-key locks to avoid shared-lock upgrade deadlocks.
12
13
  claim = claim.on_duplicate_key_update(*key.keys) if database.database_type == :mysql
13
14
  claim.insert(key)
@@ -21,11 +21,10 @@ module Legion
21
21
  def append(stream:, type:, data: {}, metadata: {})
22
22
  return { error: 'db unavailable' } unless db_ready?
23
23
 
24
- conn = Legion::Data.connection
25
- Legion::Data::DatabaseLock.with_claim(database: conn, table: :append_claims,
26
- key: { kind: 'event', stream_id: stream }) do
27
- records = conn[:governance_events].where(stream_id: stream).order(Sequel.desc(:sequence_number))
28
- records = records.for_update unless conn.database_type == :sqlite
24
+ database = Legion::Data::Model::GovernanceEvent.db
25
+ Legion::Data::DatabaseLock.with_claim(key: { kind: 'event', stream_id: stream }) do
26
+ records = Legion::Data::Model::GovernanceEvent.where(stream_id: stream).order(Sequel.desc(:sequence_number))
27
+ records = records.for_update unless database.database_type == :sqlite
29
28
  last = records.first
30
29
 
31
30
  seq = (last&.[](:sequence_number) || 0) + 1
@@ -35,7 +34,7 @@ module Legion
35
34
  metadata_json = Legion::JSON.dump(metadata)
36
35
  event_hash = compute_hash(stream, seq, type, data_json, metadata_json, prev_hash)
37
36
 
38
- conn[:governance_events].insert(
37
+ Legion::Data::Model::GovernanceEvent.create(
39
38
  stream_id: stream,
40
39
  event_type: type,
41
40
  sequence_number: seq,
@@ -54,7 +53,7 @@ module Legion
54
53
  def read_stream(stream, since: nil)
55
54
  return [] unless db_ready?
56
55
 
57
- ds = Legion::Data.connection[:governance_events].where(stream_id: stream)
56
+ ds = Legion::Data::Model::GovernanceEvent.where(stream_id: stream)
58
57
  ds = ds.where { created_at >= since } if since
59
58
  ds.order(:sequence_number).all.map { |e| deserialize(e) }
60
59
  end
@@ -62,7 +61,7 @@ module Legion
62
61
  def read_by_type(type, since: nil, limit: 100)
63
62
  return [] unless db_ready?
64
63
 
65
- ds = Legion::Data.connection[:governance_events].where(event_type: type)
64
+ ds = Legion::Data::Model::GovernanceEvent.where(event_type: type)
66
65
  ds = ds.where { created_at >= since } if since
67
66
  ds.order(Sequel.desc(:created_at)).limit(limit).all.map { |e| deserialize(e) }
68
67
  end
@@ -70,10 +69,10 @@ module Legion
70
69
  def verify_chain(stream)
71
70
  return { valid: false, error: 'db unavailable' } unless db_ready?
72
71
 
73
- events = Legion::Data.connection[:governance_events]
74
- .where(stream_id: stream)
75
- .order(:sequence_number)
76
- .all
72
+ events = Legion::Data::Model::GovernanceEvent
73
+ .where(stream_id: stream)
74
+ .order(:sequence_number)
75
+ .all
77
76
 
78
77
  prev_hash = '0' * 64
79
78
  legacy_hashes = 0
@@ -129,7 +128,7 @@ module Legion
129
128
  end
130
129
 
131
130
  def db_ready?
132
- defined?(Legion::Data) && Legion::Data.connection&.table_exists?(:governance_events)
131
+ Legion::Data.connected? && Legion::Data::Model::GovernanceEvent.db.table_exists?(:governance_events)
133
132
  rescue StandardError => e
134
133
  handle_exception(e, level: :warn, handled: true, operation: :event_store_db_ready?)
135
134
  false
@@ -102,16 +102,14 @@ module Legion
102
102
  end
103
103
 
104
104
  def persist_step_timings(extract_id, timings)
105
- return unless defined?(Legion::Data)
105
+ return unless Legion::Data.connected?
106
106
 
107
- connection = Legion::Data.connection
108
- return unless connection&.table_exists?(:extract_step_timings)
107
+ existing_steps = Legion::Data::Model::ExtractStepTiming.where(extract_id: extract_id).select_map(:name)
108
+ timings.each do |timing|
109
+ next if existing_steps.include?(timing[:name])
109
110
 
110
- existing_steps = connection[:extract_step_timings].where(extract_id: extract_id).select_map(:name)
111
- rows = timings.reject { |timing| existing_steps.include?(timing[:name]) }.map do |timing|
112
- timing.merge(extract_id: extract_id)
111
+ Legion::Data::Model::ExtractStepTiming.create(timing.merge(extract_id: extract_id))
113
112
  end
114
- connection[:extract_step_timings].multi_insert(rows) unless rows.empty?
115
113
  rescue StandardError => e
116
114
  handle_exception(e, level: :warn, handled: true, operation: :persist_extract_step_timings,
117
115
  extract_id: extract_id)
@@ -20,7 +20,7 @@ module Legion
20
20
  end
21
21
 
22
22
  def data_connected?
23
- defined?(Legion::Settings) && Legion::Settings[:data][:connected]
23
+ Legion::Settings[:data][:connected]
24
24
  end
25
25
 
26
26
  def data_connection
@@ -17,7 +17,7 @@ module Legion
17
17
  def setup(database: nil, **)
18
18
  return if @connected
19
19
 
20
- db_file = database || local_settings[:database] || 'legionio_local.db'
20
+ db_file = database || Legion::Settings[:data][:local][:database]
21
21
  unless File.absolute_path?(db_file)
22
22
  base_dir = File.expand_path('~/.legionio')
23
23
  FileUtils.mkdir_p(base_dir)
@@ -26,19 +26,19 @@ module Legion
26
26
  @db_path = db_file
27
27
 
28
28
  sqlite_defaults = Legion::Data::Connection::ADAPTER_DEFAULTS.fetch(:sqlite, {})
29
- data = defined?(Legion::Settings) ? Legion::Settings[:data] : {}
29
+ data = Legion::Settings[:data]
30
30
  opts = { adapter: :sqlite, database: db_file }
31
31
  Legion::Data::Connection::ADAPTER_KEYS.fetch(:sqlite, []).each do |key|
32
32
  val = data.key?(key) && !data[key].nil? ? data[key] : sqlite_defaults[key]
33
33
  opts[key] = val unless val.nil?
34
34
  end
35
- opts[:timeout] = data[:timeout] || 30_000
35
+ opts[:timeout] = data[:timeout].nil? ? 30_000 : data[:timeout]
36
36
  opts[:after_connect] = proc do |connection|
37
37
  Legion::Data::Connection.configure_sqlite_busy_handler(connection: connection, timeout: opts[:timeout])
38
38
  connection.execute_batch('PRAGMA synchronous=NORMAL; PRAGMA cache_size=-20000; PRAGMA mmap_size=268435456')
39
39
  end
40
40
 
41
- if local_settings[:query_log]
41
+ if Legion::Settings[:data][:local][:query_log]
42
42
  log_path = File.join(Legion::Data::Connection::QUERY_LOG_DIR, 'data-local-query.log')
43
43
  @query_file_logger = Legion::Data::Connection::QueryFileLogger.new(log_path)
44
44
  opts[:logger] = @query_file_logger
@@ -99,7 +99,7 @@ module Legion
99
99
  connected: true,
100
100
  adapter: :sqlite,
101
101
  path: @db_path,
102
- query_log: local_settings[:query_log] || false,
102
+ query_log: Legion::Settings[:data][:local][:query_log],
103
103
  query_log_path: @query_file_logger&.path,
104
104
  registered_migrations: registered_migrations.keys
105
105
  }
@@ -135,7 +135,7 @@ module Legion
135
135
  private
136
136
 
137
137
  def run_migrations
138
- return unless local_settings.dig(:migrations, :auto_migrate) != false
138
+ return unless Legion::Settings[:data][:local][:migrations][:auto_migrate]
139
139
 
140
140
  registered_migrations.each do |name, path|
141
141
  run_single_migration(name, path)
@@ -143,7 +143,7 @@ module Legion
143
143
  end
144
144
 
145
145
  def run_single_migration(name, path)
146
- return unless local_settings.dig(:migrations, :auto_migrate) != false
146
+ return unless Legion::Settings[:data][:local][:migrations][:auto_migrate]
147
147
  return unless File.directory?(path)
148
148
 
149
149
  table = :"schema_migrations_#{name}"
@@ -153,12 +153,6 @@ module Legion
153
153
  raise
154
154
  end
155
155
 
156
- def local_settings
157
- return {} unless defined?(Legion::Settings)
158
-
159
- Legion::Settings[:data]&.dig(:local) || {}
160
- end
161
-
162
156
  def build_local_logger
163
157
  tagged = if defined?(Legion::Logging::TaggedLogger) && respond_to?(:tagged_logger_settings, true)
164
158
  Legion::Logging::TaggedLogger.new(
@@ -181,17 +175,11 @@ module Legion
181
175
  end
182
176
 
183
177
  def resolved_sql_log_level
184
- (local_settings[:sql_log_level] || Legion::Settings[:data][:sql_log_level] || 'debug').to_sym
185
- rescue StandardError => e
186
- handle_exception(e, level: :warn, handled: true, operation: :resolved_sql_log_level)
187
- :debug
178
+ Legion::Settings[:data][:local].fetch(:sql_log_level, Legion::Settings[:data][:sql_log_level]).to_sym
188
179
  end
189
180
 
190
181
  def resolved_log_warn_duration
191
- local_settings[:log_warn_duration] || Legion::Settings[:data][:log_warn_duration]
192
- rescue StandardError => e
193
- handle_exception(e, level: :warn, handled: true, operation: :resolved_log_warn_duration)
194
- nil
182
+ Legion::Settings[:data][:local].fetch(:log_warn_duration, Legion::Settings[:data][:log_warn_duration])
195
183
  end
196
184
  end
197
185
  end
@@ -16,6 +16,30 @@ module Legion
16
16
  return
17
17
  end
18
18
 
19
+ if connection.database_type == :postgres
20
+ role_state = connection.fetch(<<~SQL).first
21
+ SELECT session_user,
22
+ current_user,
23
+ current_setting('role') AS active_role,
24
+ to_regrole('legionio_migrator')::text AS migrator_role,
25
+ CASE
26
+ WHEN to_regrole('legionio_migrator') IS NULL THEN NULL
27
+ ELSE pg_has_role(session_user, 'legionio_migrator', 'MEMBER')
28
+ END AS migrator_member,
29
+ CASE
30
+ WHEN to_regrole('legionio_migrator') IS NULL THEN NULL
31
+ ELSE pg_has_role(session_user, 'legionio_migrator', 'SET')
32
+ END AS migrator_set,
33
+ has_schema_privilege(session_user, 'public', 'CREATE') AS session_create,
34
+ has_schema_privilege(current_user, 'public', 'CREATE') AS current_create,
35
+ CASE
36
+ WHEN to_regrole('legionio_migrator') IS NULL THEN NULL
37
+ ELSE has_schema_privilege('legionio_migrator', 'public', 'CREATE')
38
+ END AS migrator_create
39
+ SQL
40
+ Legion::Logging.unknown "migration role state=#{role_state.inspect}"
41
+ end
42
+
19
43
  Legion::Settings[:data][:migrations][:version] = Sequel::Migrator.run(connection, path, **)
20
44
  log.info("Legion::Data::Migration ran successfully to version #{Legion::Settings[:data][:migrations][:version]}")
21
45
  Legion::Settings[:data][:migrations][:ran] = true
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ Sequel.migration do
4
+ change do
5
+ create_table(:task_logs) do
6
+ primary_key :id
7
+ String :uuid, size: 36, null: false, unique: true
8
+ String :access_scope, size: 20, null: false, default: 'global', index: true
9
+ foreign_key :identity_principal_id, :identity_principals, null: true, on_delete: :set_null, on_update: :cascade
10
+ foreign_key :identity_id, :identities, null: true, on_delete: :set_null, on_update: :cascade
11
+ String :identity_canonical_name, size: 255, null: true, index: true
12
+ foreign_key :task_id, :tasks, null: true, on_delete: :set_null, on_update: :cascade
13
+ foreign_key :node_id, :nodes, null: true, on_delete: :set_null, on_update: :cascade
14
+ foreign_key :function_id, :functions, null: true, on_delete: :set_null, on_update: :cascade
15
+ String :entry, text: true, null: false
16
+ DateTime :created, null: false, default: Sequel::CURRENT_TIMESTAMP
17
+ DateTime :created_at, null: false, default: Sequel::CURRENT_TIMESTAMP
18
+ DateTime :inserted_at, null: false, default: Sequel::CURRENT_TIMESTAMP
19
+ DateTime :updated_at, null: true
20
+ index :identity_principal_id
21
+ index :task_id
22
+ index :node_id
23
+ index :function_id
24
+ index :created
25
+ end
26
+ end
27
+ end
@@ -11,9 +11,9 @@ module Legion
11
11
  attr_reader :loaded_models
12
12
 
13
13
  def models
14
- %w[extension function relationship chain task runner node setting digital_worker
14
+ %w[extension function relationship chain task task_log runner node setting digital_worker
15
15
  apollo_entry apollo_relation apollo_expertise apollo_access_log audit_log
16
- audit_record extract_step_timing
16
+ audit_record governance_event append_claim data_archive extract_step_timing
17
17
  identity/identity identity/principal identity/providers identity/group
18
18
  identity/group_memberships identity/audit_log
19
19
  apollo/entries apollo/relation apollo/access_log apollo/expertise
@@ -30,10 +30,7 @@ module Legion
30
30
  def load
31
31
  log.info 'Loading Legion::Data::Models'
32
32
  @loaded_models ||= []
33
- database = Legion::Data::Connection.sequel
34
- Sequel::Model.db = database
35
33
  require_sequel_models(models)
36
- bind_database(namespace: Legion::Data::Model, database: database)
37
34
  Legion::Settings[:data][:models][:loaded] = true
38
35
  end
39
36
 
@@ -52,22 +49,6 @@ module Legion
52
49
  handle_exception(e, level: :fatal, operation: :load_sequel_model, model: model)
53
50
  raise e unless Legion::Settings[:data][:models][:continue_on_load_fail]
54
51
  end
55
-
56
- private
57
-
58
- def bind_database(namespace:, database:)
59
- namespace.constants(false).each do |name|
60
- value = namespace.const_get(name, false)
61
- if value.is_a?(Class) && value < Sequel::Model
62
- next if value.db.equal?(database)
63
-
64
- value.set_dataset(database[value.table_name])
65
- value.association_reflections.each_value { |reflection| reflection[:cache]&.clear }
66
- elsif value.is_a?(Module)
67
- bind_database(namespace: value, database: database)
68
- end
69
- end
70
- end
71
52
  end
72
53
  end
73
54
  end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Data
5
+ module Model
6
+ class AppendClaim < Sequel::Model(:append_claims)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Data
5
+ module Model
6
+ class DataArchive < Sequel::Model(:data_archive)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Legion
4
+ module Data
5
+ module Model
6
+ class GovernanceEvent < Sequel::Model(:governance_events)
7
+ end
8
+ end
9
+ end
10
+ end
@@ -2,15 +2,15 @@
2
2
 
3
3
  require 'digest'
4
4
  require 'legion/json'
5
+ require 'legion/data/task/status'
5
6
  require 'time'
6
7
 
7
8
  module Legion
8
9
  module Data
9
10
  module Model
10
11
  class Task < Sequel::Model
11
- TERMINAL_STATUSES = %w[
12
- completed complete failed error cancelled canceled timeout timed_out
13
- ].freeze
12
+ TERMINAL_STATUSES = (Legion::Data::Task::Status::TERMINAL_STATUSES +
13
+ Legion::Data::Task::Status::LEGACY_TERMINAL_STATUSES).freeze
14
14
 
15
15
  many_to_one :function
16
16
  many_to_one :relationship
@@ -60,9 +60,9 @@ module Legion
60
60
  when Array
61
61
  value.map { |item| canonical_payload(item) }
62
62
  when Time
63
- value.utc.iso8601(6)
63
+ value.getutc.iso8601(6)
64
64
  when DateTime
65
- value.to_time.utc.iso8601(6)
65
+ value.to_time.getutc.iso8601(6)
66
66
  else
67
67
  value
68
68
  end
@@ -1,11 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'securerandom'
4
+
3
5
  module Legion
4
6
  module Data
5
7
  module Model
6
8
  class TaskLog < Sequel::Model
7
9
  many_to_one :task
8
10
  many_to_one :node
11
+ many_to_one :function
12
+
13
+ def self.insert(values)
14
+ create(values).id
15
+ end
16
+
17
+ def before_create
18
+ self[:uuid] ||= SecureRandom.uuid
19
+ self[:created] ||= Time.now
20
+ self[:created] = self[:created].getlocal if self[:created].is_a?(Time)
21
+ self[:created_at] ||= self[:created]
22
+ self[:created_at] = self[:created_at].getlocal if self[:created_at].is_a?(Time)
23
+ super
24
+ end
9
25
  end
10
26
  end
11
27
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'legion/logging/helper'
4
+ require 'legion/settings'
4
5
 
5
6
  module Legion
6
7
  module Data
@@ -76,10 +77,6 @@ module Legion
76
77
  keepalives_count: 3,
77
78
  tcp_user_timeout: 15_000,
78
79
 
79
- # Shutdown: max seconds to wait for checked-out connections to return before
80
- # force-disconnecting them.
81
- shutdown_timeout: 5,
82
-
83
80
  # Adapter-specific (nil = use adapter built-in default)
84
81
  connect_timeout: nil,
85
82
  read_timeout: nil,
@@ -95,6 +92,7 @@ module Legion
95
92
 
96
93
  # Grouped settings
97
94
  creds: creds,
95
+ tls: { enabled: false },
98
96
  cache: cache,
99
97
  migrations: migrations,
100
98
  models: models,
@@ -141,7 +139,10 @@ module Legion
141
139
  def self.archival
142
140
  {
143
141
  retention_days: 90,
142
+ warm_after_days: 7,
143
+ cold_after_days: 90,
144
144
  batch_size: 1000,
145
+ tables: %w[tasks metering_records],
145
146
  storage_backend: nil
146
147
  }
147
148
  end
@@ -158,8 +159,4 @@ module Legion
158
159
  end
159
160
  end
160
161
 
161
- begin
162
- Legion::Settings.merge_settings('data', Legion::Data::Settings.default) if Legion.const_defined?('Settings', false)
163
- rescue StandardError => e
164
- Legion::Data::Settings.handle_exception(e, level: :fatal, operation: :merge_settings)
165
- end
162
+ Legion::Settings.register_library(:data, Legion::Data::Settings.default)