mudis-ql 0.2.0 → 0.2.1

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: ca08d464b1ccfec7dcca637fa7fcf3e80e59fc5175ad1875ae785a6e6e204f9a
4
- data.tar.gz: a00f60cf704c7b7b7df56570c2addbb926beb31599c411047d209dea47d3b4f5
3
+ metadata.gz: 5d6b6429e7f8bd20bea39f00e45a7557c7726b1452bd1c20f7cd3d0825fff42e
4
+ data.tar.gz: caeef29d56a5205fcef533e54689d1b866aa7a714dc089cb66e85718ae7324ff
5
5
  SHA512:
6
- metadata.gz: 934c5dc7d6bfd8fd3dd71dc875a0cc967b33c618cc1ca2b47602462ef31db0d09dc40d8a6d67e93cd3472a2d78cc2a9d52aa583b620c6d95e4ca2278b5b9ab2f
7
- data.tar.gz: bb29da619a4be61e0090955cab91ae96cdfd0824a65b3becce4694ae23aa87c37b00ea873f2a4cc897f3f02851b403b24c748fc861a7544566b8fc29a75dc9d3
6
+ metadata.gz: 64f95d197db3478067b9d2943d892a1bfeeba2898a061a5e20587d40b2b81887b808e409fb82657f840f263a922d1a76bc679134a261eb1630e82e3b7df46dcd
7
+ data.tar.gz: d300fe27f9181f04d83f1a70778bb1337e0bc6ecfb81a651b5d1d48404eab77236723e9ae13c957659d18f4aa2979fef18ef46684fcf35faa8f19607f574bbcd
data/README.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # Mudis-QL
2
2
 
3
+ [![RubyMine](https://www.elegantobjects.org/rubymine.svg)](https://www.jetbrains.com/ruby/)
4
+
3
5
  [![Gem Version](https://badge.fury.io/rb/mudis-ql.svg)](https://badge.fury.io/rb/mudis-ql)
4
- [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT)
7
+ [![Documentation](https://img.shields.io/badge/docs-rubydoc.info-blue.svg)](https://www.rubydoc.info/github/kiebor81/mudis-ql)
5
8
 
6
9
  A simple query DSL for [mudis](https://github.com/kiebor81/mudis) cache. Mudis-QL extends mudis by providing a SQL-like query interface for data stored in the cache, enabling you to filter, sort, and paginate cached data without needing a full database.
7
10
 
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MudisQL
4
+ # Utility for deep-duplicating nested objects to avoid mutating cached data
5
+ module DeepDup
6
+ def self.call(obj) # rubocop:disable Metrics/MethodLength
7
+ case obj
8
+ when Hash
9
+ obj.transform_values { |v| call(v) }
10
+ when Array
11
+ obj.map { |v| call(v) }
12
+ else
13
+ begin
14
+ obj.dup
15
+ rescue TypeError
16
+ obj
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -18,7 +18,7 @@ module MudisQL
18
18
  #
19
19
  # @return [Hash] top-level metrics
20
20
  def summary
21
- @metrics_data.reject { |k, _| [:least_touched, :buckets].include?(k) }
21
+ @metrics_data.reject { |k, _| %i[least_touched buckets].include?(k) }
22
22
  end
23
23
 
24
24
  # Query least touched keys
@@ -46,7 +46,7 @@ module MudisQL
46
46
  # @return [Integer] total key count
47
47
  def total_keys
48
48
  buckets_data = @metrics_data[:buckets] || []
49
- buckets_data.sum { |b| (b[:keys] || b["keys"] || 0) }
49
+ buckets_data.sum { |b| b[:keys] || b['keys'] || 0 }
50
50
  end
51
51
 
52
52
  # Get total memory across all buckets
@@ -86,7 +86,7 @@ module MudisQL
86
86
  # @return [Array<Hash>] buckets exceeding threshold
87
87
  def high_memory_buckets(threshold)
88
88
  buckets_data = @metrics_data[:buckets] || []
89
- buckets_data.select { |b| ((b[:memory_bytes] || b["memory_bytes"]) || 0) > threshold }
89
+ buckets_data.select { |b| ((b[:memory_bytes] || b['memory_bytes']) || 0) > threshold }
90
90
  end
91
91
 
92
92
  # Find buckets with many keys
@@ -95,7 +95,7 @@ module MudisQL
95
95
  # @return [Array<Hash>] buckets exceeding threshold
96
96
  def high_key_buckets(threshold)
97
97
  buckets_data = @metrics_data[:buckets] || []
98
- buckets_data.select { |b| ((b[:keys] || b["keys"]) || 0) > threshold }
98
+ buckets_data.select { |b| ((b[:keys] || b['keys']) || 0) > threshold }
99
99
  end
100
100
 
101
101
  # Get bucket distribution statistics
@@ -105,8 +105,8 @@ module MudisQL
105
105
  buckets_data = @metrics_data[:buckets] || []
106
106
  return default_distribution if buckets_data.empty?
107
107
 
108
- key_counts = buckets_data.map { |b| (b[:keys] || b["keys"]) || 0 }
109
- memory_values = buckets_data.map { |b| (b[:memory_bytes] || b["memory_bytes"]) || 0 }
108
+ key_counts = buckets_data.map { |b| (b[:keys] || b['keys']) || 0 }
109
+ memory_values = buckets_data.map { |b| (b[:memory_bytes] || b['memory_bytes']) || 0 }
110
110
 
111
111
  {
112
112
  total_buckets: buckets_data.size,
@@ -156,7 +156,7 @@ module MudisQL
156
156
  def create_scope_for_array(data)
157
157
  # Create a temporary store-like object for the array data
158
158
  temp_store = Object.new
159
- temp_store.define_singleton_method(:all) { data }
159
+ temp_store.define_singleton_method(:all) { data.map { |item| DeepDup.call(item) } }
160
160
  Scope.new(temp_store)
161
161
  end
162
162
 
@@ -35,9 +35,11 @@ module MudisQL
35
35
  # query.where(age: ->(v) { v > 18 })
36
36
  # query.where(name: /^A/)
37
37
  def where(conditions)
38
- @conditions = @conditions.dup unless @conditions.frozen?
39
- @conditions << conditions
40
- self
38
+ cloned = clone
39
+ cloned_conditions = cloned.instance_variable_get(:@conditions).dup
40
+ cloned_conditions << conditions
41
+ cloned.instance_variable_set(:@conditions, cloned_conditions)
42
+ cloned
41
43
  end
42
44
 
43
45
  # Order results by a field
@@ -46,9 +48,10 @@ module MudisQL
46
48
  # @param direction [Symbol] :asc or :desc
47
49
  # @return [Scope] self for chaining
48
50
  def order(field, direction = :asc)
49
- @order_by = field.to_s
50
- @order_direction = direction
51
- self
51
+ cloned = clone
52
+ cloned.instance_variable_set(:@order_by, field.to_s)
53
+ cloned.instance_variable_set(:@order_direction, direction)
54
+ cloned
52
55
  end
53
56
 
54
57
  # Limit the number of results
@@ -56,8 +59,9 @@ module MudisQL
56
59
  # @param value [Integer] maximum number of results
57
60
  # @return [Scope] self for chaining
58
61
  def limit(value)
59
- @limit_value = value
60
- self
62
+ cloned = clone
63
+ cloned.instance_variable_set(:@limit_value, value)
64
+ cloned
61
65
  end
62
66
 
63
67
  # Skip the first N results
@@ -65,8 +69,9 @@ module MudisQL
65
69
  # @param value [Integer] number of results to skip
66
70
  # @return [Scope] self for chaining
67
71
  def offset(value)
68
- @offset_value = value
69
- self
72
+ cloned = clone
73
+ cloned.instance_variable_set(:@offset_value, value)
74
+ cloned
70
75
  end
71
76
 
72
77
  # Execute the query and return all matching records
@@ -76,15 +81,14 @@ module MudisQL
76
81
  results = store.all
77
82
  results = apply_conditions(results)
78
83
  results = apply_order(results)
79
- results = apply_pagination(results)
80
- results
84
+ apply_pagination(results)
81
85
  end
82
86
 
83
87
  # Execute query and return first result
84
88
  #
85
89
  # @return [Hash, nil] first matching record or nil
86
90
  def first
87
- limit(1).all.first
91
+ clone.limit(1).all.first
88
92
  end
89
93
 
90
94
  # Execute query and return last result
@@ -105,7 +109,7 @@ module MudisQL
105
109
  #
106
110
  # @return [Boolean] true if at least one record matches
107
111
  def exists?
108
- count > 0
112
+ count.positive?
109
113
  end
110
114
 
111
115
  # Sum numeric values of a field across matching records
@@ -144,7 +148,7 @@ module MudisQL
144
148
  def group_by(field)
145
149
  field_str = field.to_s
146
150
  filtered = apply_conditions(store.all)
147
-
151
+
148
152
  filtered.group_by do |record|
149
153
  record[field_str]
150
154
  end
@@ -209,7 +213,7 @@ module MudisQL
209
213
  # Separate nil and non-nil values
210
214
  non_nil_results = []
211
215
  nil_results = []
212
-
216
+
213
217
  results.each do |record|
214
218
  val = record[@order_by]
215
219
  if val.nil?
@@ -234,7 +238,7 @@ module MudisQL
234
238
 
235
239
  # Append nil values at the end
236
240
  sorted + nil_results
237
- rescue ArgumentError => e
241
+ rescue ArgumentError
238
242
  # If sorting fails, return unsorted results
239
243
  results
240
244
  end
@@ -245,7 +249,7 @@ module MudisQL
245
249
  # @return [Array<Hash>] paginated records
246
250
  def apply_pagination(results)
247
251
  offset = [@offset_value, 0].max
248
- results = results.drop(offset) if offset > 0
252
+ results = results.drop(offset) if offset.positive?
249
253
  results = results.take(@limit_value) if @limit_value && @limit_value >= 0
250
254
  results
251
255
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "mudis"
3
+ require 'mudis'
4
4
 
5
5
  module MudisQL
6
6
  # Store wraps mudis operations for a specific namespace
@@ -20,7 +20,7 @@ module MudisQL
20
20
  else
21
21
  # When no namespace, mudis uses default internal namespace
22
22
  # We need to call without the namespace parameter
23
- [] # mudis doesn't support listing keys without namespace
23
+ [] # mudis doesn't support listing keys without namespace
24
24
  end
25
25
  end
26
26
 
@@ -64,16 +64,22 @@ module MudisQL
64
64
  #
65
65
  # @return [Array<Hash>] array of records with their keys
66
66
  def all
67
- keys.map do |key|
68
- value = read(key)
69
- next unless value
67
+ keys.filter_map { |key| build_record(key) }
68
+ end
69
+
70
+ private
71
+
72
+ def build_record(key)
73
+ value = read(key)
74
+ return if value.nil?
70
75
 
71
- if value.is_a?(Hash)
72
- value.merge("_key" => key)
73
- else
74
- { "_key" => key, "value" => value }
75
- end
76
- end.compact
76
+ if value.is_a?(Hash)
77
+ record = DeepDup.call(value)
78
+ record['_key'] = key
79
+ record
80
+ else
81
+ { '_key' => key, 'value' => DeepDup.call(value) }
82
+ end
77
83
  end
78
84
  end
79
85
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module MudisQL
4
- VERSION = "0.2.0"
4
+ VERSION = '0.2.1'
5
5
  end
data/lib/mudis-ql.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "mudis-ql/version"
4
- require_relative "mudis-ql/store"
5
- require_relative "mudis-ql/scope"
6
- require_relative "mudis-ql/metrics_scope"
3
+ require_relative 'mudis-ql/version'
4
+ require_relative 'mudis-ql/deep_dup'
5
+ require_relative 'mudis-ql/store'
6
+ require_relative 'mudis-ql/scope'
7
+ require_relative 'mudis-ql/metrics_scope'
7
8
 
8
9
  # MudisQL provides a simple query DSL for mudis cache
9
10
  module MudisQL
@@ -0,0 +1,6 @@
1
+ module MudisQL
2
+ # Utility for deep-duplicating nested objects
3
+ module DeepDup
4
+ def self.call: (untyped obj) -> untyped
5
+ end
6
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mudis-ql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - kiebor81
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2026-01-02 00:00:00.000000000 Z
10
+ date: 2026-02-03 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: mudis
@@ -15,61 +15,20 @@ dependencies:
15
15
  requirements:
16
16
  - - "~>"
17
17
  - !ruby/object:Gem::Version
18
- version: 0.9.0
18
+ version: 0.9.4
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - "~>"
24
24
  - !ruby/object:Gem::Version
25
- version: 0.9.0
26
- - !ruby/object:Gem::Dependency
27
- name: climate_control
28
- requirement: !ruby/object:Gem::Requirement
29
- requirements:
30
- - - "~>"
31
- - !ruby/object:Gem::Version
32
- version: 1.1.0
33
- type: :development
34
- prerelease: false
35
- version_requirements: !ruby/object:Gem::Requirement
36
- requirements:
37
- - - "~>"
38
- - !ruby/object:Gem::Version
39
- version: 1.1.0
40
- - !ruby/object:Gem::Dependency
41
- name: rspec
42
- requirement: !ruby/object:Gem::Requirement
43
- requirements:
44
- - - "~>"
45
- - !ruby/object:Gem::Version
46
- version: '3.12'
47
- type: :development
48
- prerelease: false
49
- version_requirements: !ruby/object:Gem::Requirement
50
- requirements:
51
- - - "~>"
52
- - !ruby/object:Gem::Version
53
- version: '3.12'
54
- - !ruby/object:Gem::Dependency
55
- name: simplecov
56
- requirement: !ruby/object:Gem::Requirement
57
- requirements:
58
- - - "~>"
59
- - !ruby/object:Gem::Version
60
- version: '0.22'
61
- type: :development
62
- prerelease: false
63
- version_requirements: !ruby/object:Gem::Requirement
64
- requirements:
65
- - - "~>"
66
- - !ruby/object:Gem::Version
67
- version: '0.22'
25
+ version: 0.9.4
68
26
  description: Mudis-QL extends Mudis by providing a fluent SQL-like query interface
69
27
  for data stored in the mudis cache
70
28
  executables: []
71
29
  extensions: []
72
30
  extra_rdoc_files:
31
+ - sig/mudis-ql/deep_dup.rbs
73
32
  - sig/mudis-ql/metrics_scope.rbs
74
33
  - sig/mudis-ql/scope.rbs
75
34
  - sig/mudis-ql/store.rbs
@@ -77,21 +36,16 @@ extra_rdoc_files:
77
36
  files:
78
37
  - README.md
79
38
  - lib/mudis-ql.rb
39
+ - lib/mudis-ql/deep_dup.rb
80
40
  - lib/mudis-ql/metrics_scope.rb
81
41
  - lib/mudis-ql/scope.rb
82
42
  - lib/mudis-ql/store.rb
83
43
  - lib/mudis-ql/version.rb
84
44
  - sig/mudis-ql.rbs
45
+ - sig/mudis-ql/deep_dup.rbs
85
46
  - sig/mudis-ql/metrics_scope.rbs
86
47
  - sig/mudis-ql/scope.rbs
87
48
  - sig/mudis-ql/store.rbs
88
- - spec/mudis-ql/error_handling_spec.rb
89
- - spec/mudis-ql/integration_spec.rb
90
- - spec/mudis-ql/metrics_scope_spec.rb
91
- - spec/mudis-ql/performance_spec.rb
92
- - spec/mudis-ql/scope_spec.rb
93
- - spec/mudis-ql/store_spec.rb
94
- - spec/mudis-ql_spec.rb
95
49
  homepage: https://github.com/kiebor81/mudis-ql
96
50
  licenses:
97
51
  - MIT
@@ -99,6 +53,7 @@ metadata:
99
53
  homepage_uri: https://github.com/kiebor81/mudis-ql
100
54
  source_code_uri: https://github.com/kiebor81/mudis-ql
101
55
  changelog_uri: https://github.com/kiebor81/mudis-ql/blob/main/CHANGELOG.md
56
+ rubygems_mfa_required: 'true'
102
57
  rdoc_options: []
103
58
  require_paths:
104
59
  - lib
@@ -106,7 +61,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
106
61
  requirements:
107
62
  - - ">="
108
63
  - !ruby/object:Gem::Version
109
- version: '3.0'
64
+ version: '3.3'
110
65
  required_rubygems_version: !ruby/object:Gem::Requirement
111
66
  requirements:
112
67
  - - ">="
@@ -116,11 +71,4 @@ requirements: []
116
71
  rubygems_version: 3.6.2
117
72
  specification_version: 4
118
73
  summary: A simple query DSL for Mudis cache
119
- test_files:
120
- - spec/mudis-ql/error_handling_spec.rb
121
- - spec/mudis-ql/integration_spec.rb
122
- - spec/mudis-ql/metrics_scope_spec.rb
123
- - spec/mudis-ql/performance_spec.rb
124
- - spec/mudis-ql/scope_spec.rb
125
- - spec/mudis-ql/store_spec.rb
126
- - spec/mudis-ql_spec.rb
74
+ test_files: []