redcord 0.0.3 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
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