legion-data 1.10.5 → 1.10.6

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f3b320363f209f8dfae3ad1a9757bae5e17dd4d7e6327b849b0d8804df22c07
4
- data.tar.gz: ac12848278ac407233eb43b6f5a72dbf503b030a9d404e88578fdb8ebd173cc5
3
+ metadata.gz: 861fe6533a77e8819c03400430f32ddb420a7cfa29e042b3c86734f6d7fd57bc
4
+ data.tar.gz: 48fe377db280cad64c5e9331926a24319a44c78c96eeb9aa7e2c6aa038a77024
5
5
  SHA512:
6
- metadata.gz: 0e0331f06f446400f70581981a8f083e1baac336aee984904f56af60eb9a9d021d56af48c8b845a13beaebd4aca1ba0e7a264af1101f78426d447a4cfd3d86b2
7
- data.tar.gz: 70b599bee80873cd661bdd09aacb406da9d8cdd479d270b6012032945aedb08bb82a3819f00f11f44e45b3470b8b88042491e5e892900564d334d6b4748f945a
6
+ metadata.gz: 3850a5774dbc1de772fd8a2b4762dddc9da3164e9cff32b5f02b946f7608dba551394bcb3b2aa90590f038199f33da655957c74896ff74419e840a4769b7008e
7
+ data.tar.gz: 006b1ed6fd955a876dabfa6875fa075eb8abfec1aa59467b3411e36e3ce32752735277b4013ba908db280cb98a4c152bb91e14563be55c41d6ff53778c3f944a
data/.rubocop.yml CHANGED
@@ -23,6 +23,13 @@ Naming/VariableNumber:
23
23
  - lib/legion/data/connection.rb
24
24
  Legion/Framework/EagerSequelModel:
25
25
  Enabled: false
26
+ # TaxonomyEnum validates LLM lane taxonomy (:tier/:type/:circuit_state). In
27
+ # these paths `type:` is a Sequel column type (e.g. foreign_key type: :uuid) or
28
+ # the extract API (type: :auto/:text) — not LLM taxonomy — so the cop misfires.
29
+ Legion/Llm/TaxonomyEnum:
30
+ Exclude:
31
+ - 'lib/legion/data/migrations/**/*'
32
+ - 'spec/**/*'
26
33
  Metrics/BlockLength:
27
34
  Max: 100
28
35
  Exclude:
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Legion::Data Changelog
2
2
 
3
+ ## [1.10.6] - 2026-07-03
4
+
5
+ ### Changed
6
+ - Migration 136: drops the `(conversation_id, seq)` UNIQUE constraint on `llm_messages`, replacing it with a NON-unique composite index. A conversation is a tree, not a line — a single parent can legitimately have two children at the same depth (e.g. a failed branch and the branch that continued), so two distinct messages can share `(conversation_id, seq)` and that is truth, not a duplicate. The unique constraint rejected legitimate siblings and forced the centralized ledger into a racy `MAX(seq)+1` generation that collided under concurrent writers (`PG::UniqueViolation` on `llm_messages_conversation_id_seq_key`). Message identity remains guaranteed by the unique `uuid`; `seq` becomes descriptive tree-depth. On SQLite the constraint drop rebuilds the table (dropping the inline `uuid` UNIQUE), so the migration re-asserts the uuid unique index — a no-op on PostgreSQL where `DROP CONSTRAINT` is surgical.
7
+
3
8
  ## [1.10.5] - 2026-06-16
4
9
 
5
10
  ### Added
@@ -97,18 +97,15 @@ module Legion
97
97
  total_rows = 0
98
98
  paths = []
99
99
 
100
- loop do
101
- batch_result = archive_batch(
102
- conn: conn,
103
- table: table,
104
- cutoff: cutoff,
105
- batch_size: batch_size,
106
- batch_n: batches + 1,
107
- now: now,
108
- storage_backend: storage_backend
109
- )
110
- break unless batch_result
111
-
100
+ while (batch_result = archive_batch(
101
+ conn: conn,
102
+ table: table,
103
+ cutoff: cutoff,
104
+ batch_size: batch_size,
105
+ batch_n: batches + 1,
106
+ now: now,
107
+ storage_backend: storage_backend
108
+ ))
112
109
  batches += 1
113
110
  total_rows += batch_result[:row_count]
114
111
  paths << batch_result[:path]
@@ -53,7 +53,7 @@ module Legion
53
53
  require gem_name
54
54
  true
55
55
  rescue LoadError => e
56
- handle_exception(e, level: :debug, handled: true, operation: :extract_handler_available, handler: name, gem: gem_name)
56
+ handle_exception(e, level: :warn, handled: true, operation: :extract_handler_available, handler: name, gem: gem_name)
57
57
  false
58
58
  end
59
59
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The (conversation_id, seq) UNIQUE constraint modeled a conversation as a flat
4
+ # line, but a conversation is a tree: a single parent can legitimately have two
5
+ # children at the same depth (e.g. a failed branch and the branch that
6
+ # succeeded), so two distinct messages can share the same (conversation_id, seq)
7
+ # and that is TRUTH, not a duplicate. The unique constraint rejected those
8
+ # legitimate siblings and forced the ledger into a racy MAX(seq)+1 generation
9
+ # that collided under concurrent writers.
10
+ #
11
+ # Message identity is guaranteed by the unique `uuid` (producer-derived, stable
12
+ # across redelivery). seq/parent become descriptive ordering data, so we keep a
13
+ # NON-unique composite index for conversation-ordered reads.
14
+ Sequel.migration do
15
+ up do
16
+ alter_table(:llm_messages) do
17
+ drop_constraint(:llm_messages_conversation_id_seq_key, type: :unique)
18
+ add_index %i[conversation_id seq], name: :idx_llm_messages_conversation_seq
19
+ end
20
+ # SQLite emulates the constraint drop by rebuilding the table, which drops
21
+ # the inline `uuid` UNIQUE. Re-assert it so message identity/dedup is never
22
+ # lost. On PostgreSQL DROP CONSTRAINT is surgical and the original uuid index
23
+ # already exists, so this is a no-op there.
24
+ alter_table(:llm_messages) do
25
+ add_index :uuid, unique: true, name: :idx_llm_messages_uuid_unique, if_not_exists: true
26
+ end
27
+ end
28
+
29
+ down do
30
+ alter_table(:llm_messages) do
31
+ drop_index :uuid, name: :idx_llm_messages_uuid_unique, if_exists: true
32
+ drop_index %i[conversation_id seq], name: :idx_llm_messages_conversation_seq
33
+ add_unique_constraint %i[conversation_id seq], name: :llm_messages_conversation_id_seq_key
34
+ end
35
+ end
36
+ end
@@ -18,7 +18,7 @@ module Legion
18
18
 
19
19
  ::JSON.parse(embedding)
20
20
  rescue ::JSON::ParserError => e
21
- handle_exception(e, level: :debug, handled: true, operation: :embedding_vector, id: self[:id])
21
+ handle_exception(e, level: :warn, handled: true, operation: :embedding_vector, id: self[:id])
22
22
  nil
23
23
  end
24
24
 
@@ -17,7 +17,7 @@ module Legion
17
17
 
18
18
  Legion::JSON.load(metrics)
19
19
  rescue StandardError => e
20
- handle_exception(e, level: :debug, handled: true, operation: :parsed_metrics, id: self[:id])
20
+ handle_exception(e, level: :warn, handled: true, operation: :parsed_metrics, id: self[:id])
21
21
  nil
22
22
  end
23
23
 
@@ -26,7 +26,7 @@ module Legion
26
26
 
27
27
  Legion::JSON.load(hosted_worker_ids)
28
28
  rescue StandardError => e
29
- handle_exception(e, level: :debug, handled: true, operation: :parsed_hosted_worker_ids, id: self[:id])
29
+ handle_exception(e, level: :warn, handled: true, operation: :parsed_hosted_worker_ids, id: self[:id])
30
30
  []
31
31
  end
32
32
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Legion
4
4
  module Data
5
- VERSION = '1.10.5'
5
+ VERSION = '1.10.6'
6
6
  end
7
7
  end
data/lib/legion/data.rb CHANGED
@@ -112,7 +112,7 @@ module Legion
112
112
  def connected?
113
113
  Legion::Settings[:data][:connected] == true
114
114
  rescue StandardError => e
115
- handle_exception(e, level: :debug, handled: true, operation: :connected?)
115
+ handle_exception(e, level: :warn, handled: true, operation: :connected?)
116
116
  false
117
117
  end
118
118
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: legion-data
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.5
4
+ version: 1.10.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Esity
@@ -282,6 +282,7 @@ files:
282
282
  - lib/legion/data/migrations/133_allow_null_context_tokens.rb
283
283
  - lib/legion/data/migrations/134_add_route_attempt_columns.rb
284
284
  - lib/legion/data/migrations/135_add_llm_context_token_accounting.rb
285
+ - lib/legion/data/migrations/136_drop_llm_messages_seq_unique.rb
285
286
  - lib/legion/data/model.rb
286
287
  - lib/legion/data/models/apollo/access_log.rb
287
288
  - lib/legion/data/models/apollo/entries.rb