redcord 0.0.3 → 0.1.3

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.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: redcord
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chan Zuckerberg Initiative
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '4'
55
+ - !ruby/object:Gem::Dependency
56
+ name: connection_pool
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 2.2.3
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 2.2.3
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: sorbet
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -162,19 +176,21 @@ files:
162
176
  - lib/redcord/attribute.rb
163
177
  - lib/redcord/base.rb
164
178
  - lib/redcord/configurations.rb
179
+ - lib/redcord/connection_pool.rb
165
180
  - lib/redcord/logger.rb
166
181
  - lib/redcord/lua_script_reader.rb
167
182
  - lib/redcord/migration.rb
183
+ - lib/redcord/migration/index.rb
168
184
  - lib/redcord/migration/migrator.rb
169
185
  - lib/redcord/migration/ttl.rb
170
186
  - lib/redcord/migration/version.rb
171
- - lib/redcord/prepared_redis.rb
172
187
  - lib/redcord/railtie.rb
173
188
  - lib/redcord/range_interval.rb
189
+ - lib/redcord/redis.rb
174
190
  - lib/redcord/redis_connection.rb
175
191
  - lib/redcord/relation.rb
176
192
  - lib/redcord/serializer.rb
177
- - lib/redcord/server_scripts/create_hash_returning_id.erb.lua
193
+ - lib/redcord/server_scripts/create_hash.erb.lua
178
194
  - lib/redcord/server_scripts/delete_hash.erb.lua
179
195
  - lib/redcord/server_scripts/find_by_attr.erb.lua
180
196
  - lib/redcord/server_scripts/find_by_attr_count.erb.lua
@@ -184,6 +200,7 @@ files:
184
200
  - lib/redcord/server_scripts/update_hash.erb.lua
185
201
  - lib/redcord/tasks/redis.rake
186
202
  - lib/redcord/tracer.rb
203
+ - lib/redcord/vacuum_helper.rb
187
204
  homepage: https://github.com/chanzuckerberg/redis-record
188
205
  licenses:
189
206
  - MIT
@@ -203,8 +220,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
203
220
  - !ruby/object:Gem::Version
204
221
  version: '0'
205
222
  requirements: []
206
- rubyforge_project:
207
- rubygems_version: 2.7.6.2
223
+ rubygems_version: 3.0.8
208
224
  signing_key:
209
225
  specification_version: 4
210
226
  summary: A Ruby ORM like Active Record, but for Redis
@@ -1,147 +0,0 @@
1
- # typed: strict
2
- require 'redis'
3
-
4
- # TODO: Rename Redcord::PreparedRedis -> Redcord::Redis
5
- class Redcord::PreparedRedis < Redis
6
- extend T::Sig
7
-
8
- sig do
9
- params(
10
- key: T.any(String, Symbol),
11
- args: T::Hash[T.untyped, T.untyped],
12
- ).returns(Integer)
13
- end
14
- def create_hash_returning_id(key, args)
15
- Redcord::Base.trace(
16
- 'redcord_redis_create_hash_returning_id',
17
- model_name: key,
18
- ) do
19
- evalsha(
20
- self.class.server_script_shas[:create_hash_returning_id],
21
- keys: [key],
22
- argv: args.to_a.flatten,
23
- ).to_i
24
- end
25
- end
26
-
27
- sig do
28
- params(
29
- model: String,
30
- id: Integer,
31
- args: T::Hash[T.untyped, T.untyped],
32
- ).void
33
- end
34
- def update_hash(model, id, args)
35
- Redcord::Base.trace(
36
- 'redcord_redis_update_hash',
37
- model_name: model,
38
- ) do
39
- evalsha(
40
- self.class.server_script_shas[:update_hash],
41
- keys: [model, id],
42
- argv: args.to_a.flatten,
43
- )
44
- end
45
- end
46
-
47
- sig do
48
- params(
49
- model: String,
50
- id: Integer
51
- ).returns(Integer)
52
- end
53
- def delete_hash(model, id)
54
- Redcord::Base.trace(
55
- 'redcord_redis_delete_hash',
56
- model_name: model,
57
- ) do
58
- evalsha(
59
- self.class.server_script_shas[:delete_hash],
60
- keys: [model, id]
61
- )
62
- end
63
- end
64
-
65
- sig do
66
- params(
67
- model: String,
68
- query_conditions: T::Hash[T.untyped, T.untyped],
69
- select_attrs: T::Set[Symbol]
70
- ).returns(T::Hash[Integer, T::Hash[T.untyped, T.untyped]])
71
- end
72
- def find_by_attr(model, query_conditions, select_attrs=Set.new)
73
- Redcord::Base.trace(
74
- 'redcord_redis_find_by_attr',
75
- model_name: model,
76
- ) do
77
- res = evalsha(
78
- self.class.server_script_shas[:find_by_attr],
79
- keys: [model] + query_conditions.to_a.flatten,
80
- argv: select_attrs.to_a.flatten
81
- )
82
- # The Lua script will return this as a flattened array.
83
- # Convert the result into a hash of {id -> model hash}
84
- res_hash = res.each_slice(2)
85
- res_hash.map { |key, val| [key.to_i, val.each_slice(2).to_h] }.to_h
86
- end
87
- end
88
-
89
- sig do
90
- params(
91
- model: String,
92
- query_conditions: T::Hash[T.untyped, T.untyped]
93
- ).returns(Integer)
94
- end
95
- def find_by_attr_count(model, query_conditions)
96
- Redcord::Base.trace(
97
- 'redcord_redis_find_by_attr_count',
98
- model_name: model,
99
- ) do
100
- evalsha(
101
- self.class.server_script_shas[:find_by_attr_count],
102
- keys: [model] + query_conditions.to_a.flatten,
103
- )
104
- end
105
- end
106
-
107
- sig { void }
108
- def load_server_scripts!
109
- script_names = Dir[File.join(
110
- __dir__,
111
- 'server_scripts/*.lua',
112
- )].map do |filename|
113
- # lib/redcord/server_scripts/find_by_attr.erb.lua -> find_by_attr
114
- T.must(filename.split('/').last).split('.').first&.to_sym
115
- end
116
-
117
- res = pipelined do
118
- script_names.each do |script_name|
119
- script(
120
- :load,
121
- Redcord::LuaScriptReader.read_lua_script(script_name.to_s),
122
- )
123
- end
124
- end
125
-
126
- if self.class.class_variable_get(:@@server_script_shas).nil?
127
- self.class.class_variable_set(
128
- :@@server_script_shas,
129
- script_names.zip(res).to_h
130
- )
131
- end
132
- end
133
-
134
- @@server_script_shas = T.let(nil, T.nilable(T::Hash[Symbol, String]))
135
-
136
- sig { returns(T::Hash[Symbol, String]) }
137
- def self.server_script_shas
138
- T.must(@@server_script_shas)
139
- end
140
-
141
- sig { void }
142
- def self.load_server_scripts!
143
- Redcord::Base.configurations[Rails.env].each do |_, config|
144
- new(**(config.symbolize_keys)).load_server_scripts!
145
- end
146
- end
147
- end
@@ -1,69 +0,0 @@
1
- --[[
2
- EVALSHA SHA1(__FILE__) [field value ...]
3
- > Time complexity: O(N) where N is the number of fields being set.
4
-
5
- Create a hash with the specified fields to their respective values stored at
6
- key when key does not exist.
7
-
8
- # Return value
9
- The id of the created hash as a string.
10
- --]]
11
-
12
- -- The arguments can be accessed by Lua using the KEYS global variable in the
13
- -- form of a one-based array (so KEYS[1], KEYS[2], ...).
14
- -- All the additional arguments should not represent key names and can be
15
- -- accessed by Lua using the ARGV global variable, very similarly to what
16
- -- happens with keys (so ARGV[1], ARGV[2], ...).
17
-
18
- -- KEYS[1] = Model.name
19
- -- ARGV[1...2N] = attr_key attr_val [attr_key attr_val ..]
20
- <%= include_lua 'shared/lua_helper_methods' %>
21
- <%= include_lua 'shared/index_helper_methods' %>
22
-
23
- -- Validate input to script before making Redis db calls
24
- if #KEYS ~= 1 then
25
- error('Expected keys to be of size 1')
26
- end
27
- if #ARGV % 2 ~= 0 then
28
- error('Expected an even number of arguments')
29
- end
30
-
31
- local model = KEYS[1]
32
-
33
- -- Call the Redis command: INCR "#{Model.name}:id_seq". If "#{Model.name}:id_seq" does
34
- -- not exist, the command returns 0. It errors if the id_seq overflows a 64 bit
35
- -- signed integer.
36
- redis.call('incr', model .. ':id_seq')
37
-
38
- -- The Lua version used by Redis does not support 64 bit integers:
39
- -- https://github.com/antirez/redis/issues/5261
40
- -- We ignore the integer response from INCR and use the string response from
41
- -- the GET/MGET command.
42
- local id, ttl = unpack(redis.call('mget', model .. ':id_seq', model .. ':ttl'))
43
- local key = model .. ':id:' .. id
44
-
45
- -- Forward the script arguments to the Redis command HSET.
46
- -- Call the Redis command: HSET "#{Model.name}:id:#{id}" field value ...
47
- redis.call('hset', key, unpack(ARGV))
48
-
49
- -- Set TTL on key
50
- if ttl and ttl ~= '-1' then
51
- redis.call('expire', key, ttl)
52
- end
53
-
54
- -- Add id value for any index and range index attributes
55
- local attrs_hash = to_hash(ARGV)
56
- local index_attr_keys = redis.call('smembers', model .. ':index_attrs')
57
- if #index_attr_keys > 0 then
58
- for _, attr_key in ipairs(index_attr_keys) do
59
- add_id_to_index_attr(model, attr_key, attrs_hash[attr_key], id)
60
- end
61
- end
62
- local range_index_attr_keys = redis.call('smembers', model .. ':range_index_attrs')
63
- attrs_hash['id'] = id
64
- if #range_index_attr_keys > 0 then
65
- for _, attr_key in ipairs(range_index_attr_keys) do
66
- add_id_to_range_index_attr(model, attr_key, attrs_hash[attr_key], id)
67
- end
68
- end
69
- return id