activeitem 0.0.15 → 0.0.17
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/lib/active_item/associations.rb +5 -1
- data/lib/active_item/relation.rb +47 -1
- data/lib/active_item/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3a4b1c7cc7af49e67776f895886bdf472d1e801ab3280f3ea28101bd20b8a701
|
|
4
|
+
data.tar.gz: 7415931df8a26b187e4a9ab52586b67c7cea08f0fa3a476ab09b863c02250835
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b8c97c1ffadb921d440702b5299cf4bb219ba97ad0351cef7bebfea1125e74bf027ddc0546e1a254da8d6da8952598bf170368404c6ab65074ecc8379bfaec3b
|
|
7
|
+
data.tar.gz: b9936169d15857e1423de8f622ddfe85b7be05458739f569ce1983dd6565f234ae2789f12978ac530106cc98203906a99b9666805d1e2e43c7e0a275e7c41d06
|
|
@@ -143,9 +143,13 @@ module ActiveItem
|
|
|
143
143
|
"#{association_name.to_s.camelize}Index"
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
+
# Store partition key in DynamoDB format (camelCase) for consistency
|
|
147
|
+
# with RECENT_INDEX and explicit index definitions
|
|
148
|
+
dynamo_key = to_dynamo_key(foreign_key)
|
|
149
|
+
|
|
146
150
|
@_belongs_to_indexes ||= {}
|
|
147
151
|
@_belongs_to_indexes = @_belongs_to_indexes.merge(
|
|
148
|
-
index_name => { partition_key:
|
|
152
|
+
index_name => { partition_key: dynamo_key }
|
|
149
153
|
)
|
|
150
154
|
end
|
|
151
155
|
end
|
data/lib/active_item/relation.rb
CHANGED
|
@@ -559,6 +559,12 @@ module ActiveItem
|
|
|
559
559
|
else
|
|
560
560
|
paginated_scan_with_conditions(normalized_conditions, exclusive_start_key, per_page)
|
|
561
561
|
end
|
|
562
|
+
rescue Aws::DynamoDB::Errors::ValidationException => e
|
|
563
|
+
raise unless e.message.include?('specified index')
|
|
564
|
+
|
|
565
|
+
warn "[ActiveItem] WARNING: Index not found on table '#{resolved_model.table_name}'. " \
|
|
566
|
+
'Falling back to table scan. Create the index: belt setup tables && belt deploy'
|
|
567
|
+
paginated_scan_with_conditions(normalized_conditions, exclusive_start_key, per_page)
|
|
562
568
|
rescue Aws::DynamoDB::Errors::AccessDeniedException => e
|
|
563
569
|
raise ActiveItem::AccessDeniedError.new(model_name: resolved_model.name, table: resolved_model.table_name,
|
|
564
570
|
operation: 'PaginatedQuery', original_error: e)
|
|
@@ -788,7 +794,7 @@ module ActiveItem
|
|
|
788
794
|
effective_index = index_name || resolved_model.send(:detect_index_for_conditions, normalized_conditions)
|
|
789
795
|
|
|
790
796
|
if effective_index && normalized_conditions.any?
|
|
791
|
-
|
|
797
|
+
query_with_index_or_fallback(effective_index, normalized_conditions)
|
|
792
798
|
else
|
|
793
799
|
scan_with_conditions_normalized(normalized_conditions)
|
|
794
800
|
end
|
|
@@ -838,6 +844,13 @@ module ActiveItem
|
|
|
838
844
|
end
|
|
839
845
|
|
|
840
846
|
limit_value ? [total, limit_value].min : total
|
|
847
|
+
rescue Aws::DynamoDB::Errors::ValidationException => e
|
|
848
|
+
raise unless e.message.include?('specified index')
|
|
849
|
+
|
|
850
|
+
warn "[ActiveItem] WARNING: Index not found on table '#{resolved_model.table_name}'. " \
|
|
851
|
+
'Falling back to table scan for count. Create the index: belt setup tables && belt deploy'
|
|
852
|
+
# Retry without the index
|
|
853
|
+
count_via_scan(normalized_conditions)
|
|
841
854
|
rescue Aws::DynamoDB::Errors::AccessDeniedException => e
|
|
842
855
|
raise ActiveItem::AccessDeniedError.new(model_name: resolved_model.name, table: resolved_model.table_name,
|
|
843
856
|
operation: 'Count', original_error: e)
|
|
@@ -911,6 +924,26 @@ module ActiveItem
|
|
|
911
924
|
params
|
|
912
925
|
end
|
|
913
926
|
|
|
927
|
+
# Fallback count via scan when an index is missing
|
|
928
|
+
def count_via_scan(normalized_conditions)
|
|
929
|
+
total = 0
|
|
930
|
+
exclusive_start_key = nil
|
|
931
|
+
|
|
932
|
+
loop do
|
|
933
|
+
params = build_count_scan_params(normalized_conditions)
|
|
934
|
+
params[:exclusive_start_key] = exclusive_start_key if exclusive_start_key
|
|
935
|
+
params[:limit] = limit_value if limit_value
|
|
936
|
+
|
|
937
|
+
response = resolved_model.dynamodb.scan(params)
|
|
938
|
+
total += response.count
|
|
939
|
+
exclusive_start_key = response.last_evaluated_key
|
|
940
|
+
break unless exclusive_start_key
|
|
941
|
+
break if limit_value && total >= limit_value
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
limit_value ? [total, limit_value].min : total
|
|
945
|
+
end
|
|
946
|
+
|
|
914
947
|
# Build scan params for a count-only scan
|
|
915
948
|
def build_count_scan_params(normalized_conditions)
|
|
916
949
|
filter_parts = []
|
|
@@ -1082,6 +1115,18 @@ module ActiveItem
|
|
|
1082
1115
|
foreign_key.to_s == attr_name ? nil : foreign_key.to_s
|
|
1083
1116
|
end
|
|
1084
1117
|
|
|
1118
|
+
# Attempt a GSI query, falling back to a filtered scan if the index doesn't exist.
|
|
1119
|
+
# Logs a warning when falling back so the developer knows to create the index.
|
|
1120
|
+
def query_with_index_or_fallback(idx_name, normalized_conditions)
|
|
1121
|
+
query_with_index_normalized(idx_name, normalized_conditions)
|
|
1122
|
+
rescue Aws::DynamoDB::Errors::ValidationException => e
|
|
1123
|
+
raise unless e.message.include?('specified index')
|
|
1124
|
+
|
|
1125
|
+
warn "[ActiveItem] WARNING: Index '#{idx_name}' not found on table '#{resolved_model.table_name}'. " \
|
|
1126
|
+
'Falling back to table scan. Create the index for better performance: belt setup tables && belt deploy'
|
|
1127
|
+
scan_with_conditions_normalized(normalized_conditions)
|
|
1128
|
+
end
|
|
1129
|
+
|
|
1085
1130
|
def query_with_index_normalized(idx_name, normalized_conditions)
|
|
1086
1131
|
# Get the partition key from conditions (Ruby snake_case)
|
|
1087
1132
|
ruby_partition_key = normalized_conditions.keys.first.to_s
|
|
@@ -1090,6 +1135,7 @@ module ActiveItem
|
|
|
1090
1135
|
# Get the actual DynamoDB partition key name from the index definition
|
|
1091
1136
|
# The index definition stores the DynamoDB key name (which may be camelCase)
|
|
1092
1137
|
index_config = resolved_model.indexes[idx_name] || {}
|
|
1138
|
+
# Always convert to DynamoDB key format (camelCase) for the expression
|
|
1093
1139
|
dynamo_partition_key = index_config[:partition_key]&.to_s || resolved_model.to_dynamo_key(ruby_partition_key)
|
|
1094
1140
|
|
|
1095
1141
|
return fanout_query(idx_name, normalized_conditions, index_config, dynamo_partition_key, partition_value) if partition_value.is_a?(Array)
|
data/lib/active_item/version.rb
CHANGED