familia 0.10.2 → 1.0.0.pre.rc2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.pre-commit-config.yaml +1 -1
- data/.rubocop.yml +75 -0
- data/.rubocop_todo.yml +63 -0
- data/Gemfile +6 -1
- data/Gemfile.lock +47 -15
- data/README.md +65 -13
- data/VERSION.yml +4 -3
- data/familia.gemspec +18 -13
- data/lib/familia/base.rb +33 -0
- data/lib/familia/connection.rb +87 -0
- data/lib/familia/core_ext.rb +119 -124
- data/lib/familia/errors.rb +33 -0
- data/lib/familia/features/api_version.rb +19 -0
- data/lib/familia/features/atomic_saves.rb +8 -0
- data/lib/familia/features/quantizer.rb +35 -0
- data/lib/familia/features/safe_dump.rb +194 -0
- data/lib/familia/features.rb +51 -0
- data/lib/familia/horreum/class_methods.rb +292 -0
- data/lib/familia/horreum/commands.rb +106 -0
- data/lib/familia/horreum/relations_management.rb +141 -0
- data/lib/familia/horreum/serialization.rb +193 -0
- data/lib/familia/horreum/settings.rb +63 -0
- data/lib/familia/horreum/utils.rb +44 -0
- data/lib/familia/horreum.rb +248 -0
- data/lib/familia/logging.rb +232 -0
- data/lib/familia/redistype/commands.rb +56 -0
- data/lib/familia/redistype/serialization.rb +110 -0
- data/lib/familia/redistype.rb +185 -0
- data/lib/familia/refinements.rb +88 -0
- data/lib/familia/settings.rb +38 -0
- data/lib/familia/types/hashkey.rb +107 -0
- data/lib/familia/types/list.rb +155 -0
- data/lib/familia/types/sorted_set.rb +234 -0
- data/lib/familia/types/string.rb +115 -0
- data/lib/familia/types/unsorted_set.rb +123 -0
- data/lib/familia/utils.rb +125 -0
- data/lib/familia/version.rb +25 -0
- data/lib/familia.rb +57 -161
- data/lib/redis_middleware.rb +109 -0
- data/try/00_familia_try.rb +5 -4
- data/try/10_familia_try.rb +21 -17
- data/try/20_redis_type_try.rb +67 -0
- data/try/{21_redis_object_zset_try.rb → 21_redis_type_zset_try.rb} +2 -2
- data/try/{22_redis_object_set_try.rb → 22_redis_type_set_try.rb} +2 -2
- data/try/{23_redis_object_list_try.rb → 23_redis_type_list_try.rb} +2 -2
- data/try/{24_redis_object_string_try.rb → 24_redis_type_string_try.rb} +6 -6
- data/try/{25_redis_object_hash_try.rb → 25_redis_type_hash_try.rb} +3 -3
- data/try/26_redis_bool_try.rb +10 -6
- data/try/27_redis_horreum_try.rb +93 -0
- data/try/30_familia_object_try.rb +21 -20
- data/try/35_feature_safedump_try.rb +83 -0
- data/try/40_customer_try.rb +140 -0
- data/try/41_customer_safedump_try.rb +86 -0
- data/try/test_helpers.rb +194 -0
- metadata +51 -47
- data/lib/familia/helpers.rb +0 -70
- data/lib/familia/object.rb +0 -533
- data/lib/familia/redisobject.rb +0 -1017
- data/lib/familia/test_helpers.rb +0 -40
- data/lib/familia/tools.rb +0 -67
- data/try/20_redis_object_try.rb +0 -44
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b4f3c02cad65603669b086ec26f31512004e939da510fec97fcc3803f132e5f5
|
4
|
+
data.tar.gz: cdd710ea75ff3c6ce3ccb88caef97226ee9fb549435fce605433621a8583f06d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '058e49695798298238523d571a4d21b47234874b47af018fdb085d22a430fa8db2ca725cb3103e0c8eee309b000eea7598cc4e9aed00373191d393af8d4ab27d'
|
7
|
+
data.tar.gz: 9ff11c6c341d540e69ddb9d0518b67c9463b2248899b6f74a94a92b609140ed064e303e3559a455847727d5f7581aa41fccce5fdaac5effb5d74a30202e75721
|
data/.gitignore
CHANGED
data/.pre-commit-config.yaml
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
##
|
3
|
+
# This is the RuboCop configuration file.
|
4
|
+
# It contains the rules and settings for the RuboCop linter.
|
5
|
+
#
|
6
|
+
# Enable/disable the cops individually. For more information,
|
7
|
+
# refer to the RuboCop documentation:
|
8
|
+
# https://docs.rubocop.org/rubocop/cops.html
|
9
|
+
#
|
10
|
+
# Running `rubocop --regenerate-todo` will update the todo file
|
11
|
+
# with the latest state of the onion (using the same options
|
12
|
+
# as those documented at the top of the todo file). This is
|
13
|
+
# useful for a gradual migration of the codebase.
|
14
|
+
#
|
15
|
+
inherit_from: .rubocop_todo.yml
|
16
|
+
|
17
|
+
require:
|
18
|
+
- rubocop-performance
|
19
|
+
- rubocop-thread_safety
|
20
|
+
|
21
|
+
AllCops:
|
22
|
+
NewCops: enable
|
23
|
+
UseCache: true
|
24
|
+
MaxFilesInCache: 100
|
25
|
+
TargetRubyVersion: 3.0
|
26
|
+
Exclude:
|
27
|
+
- 'migrate/**/*.rb'
|
28
|
+
- 'migrate/*.rb'
|
29
|
+
- 'try/**/*'
|
30
|
+
- 'try/*.rb'
|
31
|
+
- 'vendor/**/*'
|
32
|
+
|
33
|
+
Gemspec/DeprecatedAttributeAssignment:
|
34
|
+
Enabled: true
|
35
|
+
|
36
|
+
Gemspec/DevelopmentDependencies:
|
37
|
+
Enabled: true
|
38
|
+
|
39
|
+
Layout/HashAlignment:
|
40
|
+
Enabled: false
|
41
|
+
|
42
|
+
Lint/Void:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Metrics/AbcSize:
|
46
|
+
Enabled: false
|
47
|
+
Max: 20
|
48
|
+
|
49
|
+
Metrics/ClassLength:
|
50
|
+
Enabled: true
|
51
|
+
Max: 200
|
52
|
+
|
53
|
+
Metrics/CyclomaticComplexity:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
Metrics/MethodLength:
|
57
|
+
Enabled: true
|
58
|
+
Max: 40
|
59
|
+
CountAsOne: ['method_call']
|
60
|
+
|
61
|
+
Metrics/ModuleLength:
|
62
|
+
Enabled: true
|
63
|
+
Max: 250
|
64
|
+
CountAsOne: ['method_call']
|
65
|
+
|
66
|
+
Performance/Size:
|
67
|
+
Enabled: true
|
68
|
+
Exclude:
|
69
|
+
# - lib/example.rb
|
70
|
+
|
71
|
+
Style/NegatedIfElseCondition:
|
72
|
+
Enabled: true
|
73
|
+
|
74
|
+
Naming/AsciiIdentifiers:
|
75
|
+
Enabled: false
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2024-08-12 20:49:29 UTC using RuboCop version 1.65.0.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
# Configuration parameters: EnforcedStyle, AllowedGems, Include.
|
11
|
+
# SupportedStyles: Gemfile, gems.rb, gemspec
|
12
|
+
# Include: **/*.gemspec, **/Gemfile, **/gems.rb
|
13
|
+
Gemspec/DevelopmentDependencies:
|
14
|
+
Exclude:
|
15
|
+
- 'familia.gemspec'
|
16
|
+
|
17
|
+
# Offense count: 1
|
18
|
+
# Configuration parameters: Severity, Include.
|
19
|
+
# Include: **/*.gemspec
|
20
|
+
Gemspec/RequiredRubyVersion:
|
21
|
+
Exclude:
|
22
|
+
- 'familia.gemspec'
|
23
|
+
|
24
|
+
# Offense count: 5
|
25
|
+
# Configuration parameters: MinNameLength, AllowNamesEndingInNumbers, AllowedNames, ForbiddenNames.
|
26
|
+
# AllowedNames: as, at, by, cc, db, id, if, in, io, ip, of, on, os, pp, to
|
27
|
+
Naming/MethodParameterName:
|
28
|
+
Exclude:
|
29
|
+
- 'lib/familia/core_ext.rb'
|
30
|
+
- 'lib/familia/types/list.rb'
|
31
|
+
- 'lib/familia/types/sorted_set.rb'
|
32
|
+
- 'lib/familia/types/unsorted_set.rb'
|
33
|
+
|
34
|
+
# Offense count: 1
|
35
|
+
# Configuration parameters: NamePrefix, ForbiddenPrefixes, AllowedMethods, MethodDefinitionMacros.
|
36
|
+
# NamePrefix: is_, has_, have_
|
37
|
+
# ForbiddenPrefixes: is_, has_, have_
|
38
|
+
# AllowedMethods: is_a?
|
39
|
+
# MethodDefinitionMacros: define_method, define_singleton_method
|
40
|
+
Naming/PredicateName:
|
41
|
+
Exclude:
|
42
|
+
- 'spec/**/*'
|
43
|
+
- 'lib/familia/types/hashkey.rb'
|
44
|
+
|
45
|
+
# Offense count: 6
|
46
|
+
# Configuration parameters: AllowedConstants.
|
47
|
+
Style/Documentation:
|
48
|
+
Exclude:
|
49
|
+
- 'spec/**/*'
|
50
|
+
- 'test/**/*'
|
51
|
+
- 'lib/familia/errors.rb'
|
52
|
+
- 'lib/familia/types/hashkey.rb'
|
53
|
+
- 'lib/familia/types/list.rb'
|
54
|
+
- 'lib/familia/types/sorted_set.rb'
|
55
|
+
- 'lib/familia/types/string.rb'
|
56
|
+
- 'lib/familia/types/unsorted_set.rb'
|
57
|
+
|
58
|
+
# Offense count: 2
|
59
|
+
# This cop supports safe autocorrection (--autocorrect).
|
60
|
+
# Configuration parameters: MaxUnannotatedPlaceholdersAllowed, AllowedMethods, AllowedPatterns.
|
61
|
+
# SupportedStyles: annotated, template, unannotated
|
62
|
+
Style/FormatStringToken:
|
63
|
+
EnforcedStyle: unannotated
|
data/Gemfile
CHANGED
@@ -1,8 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'https://rubygems.org'
|
2
4
|
|
3
5
|
gemspec
|
4
6
|
|
5
7
|
group :development, :test do
|
6
8
|
gem 'pry-byebug', '~> 3.10.1', require: false
|
7
|
-
gem '
|
9
|
+
gem 'rubocop', require: false
|
10
|
+
gem 'rubocop-performance', require: false
|
11
|
+
gem 'rubocop-thread_safety', require: false
|
12
|
+
gem 'tryouts', '~> 2.4', require: false
|
8
13
|
end
|
data/Gemfile.lock
CHANGED
@@ -1,39 +1,67 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
familia (0.
|
5
|
-
gibbler (~> 1.0.0)
|
6
|
-
multi_json (~> 1.15)
|
4
|
+
familia (1.0.0.pre.rc2)
|
7
5
|
redis (>= 4.8.1, < 6.0)
|
8
|
-
|
9
|
-
uri-redis (>= 1.3.0)
|
6
|
+
uri-redis (~> 1.3)
|
10
7
|
|
11
8
|
GEM
|
12
9
|
remote: https://rubygems.org/
|
13
10
|
specs:
|
14
|
-
|
15
|
-
rake (~> 13.0.6)
|
11
|
+
ast (2.4.2)
|
16
12
|
byebug (11.1.3)
|
17
13
|
coderay (1.1.3)
|
18
14
|
connection_pool (2.4.1)
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
drydock (0.6.9)
|
16
|
+
json (2.7.2)
|
17
|
+
language_server-protocol (3.17.0.3)
|
22
18
|
method_source (1.1.0)
|
23
|
-
|
19
|
+
parallel (1.25.1)
|
20
|
+
parser (3.3.4.0)
|
21
|
+
ast (~> 2.4.1)
|
22
|
+
racc
|
24
23
|
pry (0.14.2)
|
25
24
|
coderay (~> 1.1)
|
26
25
|
method_source (~> 1.0)
|
27
26
|
pry-byebug (3.10.1)
|
28
27
|
byebug (~> 11.0)
|
29
28
|
pry (>= 0.13, < 0.15)
|
30
|
-
|
29
|
+
racc (1.8.0)
|
30
|
+
rainbow (3.1.1)
|
31
31
|
redis (5.2.0)
|
32
32
|
redis-client (>= 0.22.0)
|
33
33
|
redis-client (0.22.2)
|
34
34
|
connection_pool
|
35
|
+
regexp_parser (2.9.2)
|
36
|
+
rexml (3.3.2)
|
37
|
+
strscan
|
38
|
+
rubocop (1.65.0)
|
39
|
+
json (~> 2.3)
|
40
|
+
language_server-protocol (>= 3.17.0)
|
41
|
+
parallel (~> 1.10)
|
42
|
+
parser (>= 3.3.0.2)
|
43
|
+
rainbow (>= 2.2.2, < 4.0)
|
44
|
+
regexp_parser (>= 2.4, < 3.0)
|
45
|
+
rexml (>= 3.2.5, < 4.0)
|
46
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
47
|
+
ruby-progressbar (~> 1.7)
|
48
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
49
|
+
rubocop-ast (1.31.3)
|
50
|
+
parser (>= 3.3.1.0)
|
51
|
+
rubocop-performance (1.21.1)
|
52
|
+
rubocop (>= 1.48.1, < 2.0)
|
53
|
+
rubocop-ast (>= 1.31.1, < 2.0)
|
54
|
+
rubocop-thread_safety (0.5.1)
|
55
|
+
rubocop (>= 0.90.0)
|
56
|
+
ruby-progressbar (1.13.0)
|
35
57
|
storable (0.10.0)
|
36
|
-
|
58
|
+
strscan (3.1.0)
|
59
|
+
sysinfo (0.10.0)
|
60
|
+
drydock (< 1.0)
|
61
|
+
storable (~> 0.10)
|
62
|
+
tryouts (2.4.1)
|
63
|
+
sysinfo (~> 0.10)
|
64
|
+
unicode-display_width (2.5.0)
|
37
65
|
uri-redis (1.3.0)
|
38
66
|
|
39
67
|
PLATFORMS
|
@@ -42,9 +70,13 @@ PLATFORMS
|
|
42
70
|
ruby
|
43
71
|
|
44
72
|
DEPENDENCIES
|
73
|
+
byebug (~> 11.0)
|
45
74
|
familia!
|
46
75
|
pry-byebug (~> 3.10.1)
|
47
|
-
|
76
|
+
rubocop
|
77
|
+
rubocop-performance
|
78
|
+
rubocop-thread_safety
|
79
|
+
tryouts (~> 2.4)
|
48
80
|
|
49
81
|
BUNDLED WITH
|
50
|
-
2.5.
|
82
|
+
2.5.13
|
data/README.md
CHANGED
@@ -1,32 +1,84 @@
|
|
1
|
-
# Familia - 0.
|
1
|
+
# Familia - 1.0.0-rc2 (August 2024)
|
2
2
|
|
3
3
|
**Organize and store ruby objects in Redis. A Ruby ORM for Redis.**
|
4
4
|
|
5
|
+
Familia provides a powerful and flexible way to interact with Redis using Ruby objects. It's designed to make working with Redis as natural as working with Ruby classes.
|
6
|
+
|
5
7
|
## Installation
|
6
8
|
|
7
9
|
Get it in one of the following ways:
|
8
10
|
|
9
|
-
* In your Gemfile: `gem 'familia', '>= 0.
|
11
|
+
* In your Gemfile: `gem 'familia', '>= 1.0.0-rc2'`
|
10
12
|
* Install it by hand: `gem install familia`
|
11
13
|
* Or for development: `git clone git@github.com:delano/familia.git`
|
12
14
|
|
13
15
|
## Basic Example
|
14
16
|
|
15
17
|
```ruby
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
class Flower < Familia::Horreum
|
19
|
+
identifier :generate_id
|
20
|
+
field :token
|
21
|
+
field :name
|
22
|
+
list :owners
|
23
|
+
set :tags
|
24
|
+
zset :metrics
|
25
|
+
hashkey :props
|
26
|
+
string :counter
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
## What Familia::Horreum Can Do
|
31
|
+
|
32
|
+
Familia::Horreum provides a powerful abstraction layer over Redis, allowing you to:
|
33
|
+
|
34
|
+
1. **Define Redis-backed Ruby Classes**: As shown in the example, you can easily define classes that map to Redis structures.
|
35
|
+
|
36
|
+
2. **Use Various Redis Data Types**: Familia supports multiple Redis data types:
|
37
|
+
- `field`: For simple key-value pairs
|
38
|
+
- `list`: For Redis lists
|
39
|
+
- `set`: For Redis sets
|
40
|
+
- `zset`: For Redis sorted sets
|
41
|
+
- `hashkey`: For Redis hashes
|
42
|
+
- `string`: For Redis strings
|
43
|
+
|
44
|
+
3. **Custom Identifiers**: Use the `identifier` method to specify how objects are uniquely identified in Redis.
|
45
|
+
|
46
|
+
4. **Automatic Serialization**: Familia handles the serialization and deserialization of your objects to and from Redis.
|
47
|
+
|
48
|
+
5. **Redis Commands as Ruby Methods**: Interact with Redis using familiar Ruby syntax instead of raw Redis commands.
|
49
|
+
|
50
|
+
6. **TTL Support**: Set expiration times for your objects in Redis.
|
51
|
+
|
52
|
+
7. **Flexible Configuration**: Configure Redis connection details, serialization methods, and more.
|
53
|
+
|
54
|
+
## Advanced Features
|
55
|
+
|
56
|
+
- **API Versioning**: Familia supports API versioning to help manage changes in your data model over time.
|
57
|
+
- **Custom Serialization**: You can specify custom serialization methods for your objects.
|
58
|
+
- **Redis URI Support**: Easily connect to Redis using URI strings.
|
59
|
+
- **Debugging Tools**: Built-in debugging capabilities to help troubleshoot Redis interactions.
|
60
|
+
|
61
|
+
## Usage Example
|
62
|
+
|
63
|
+
```ruby
|
64
|
+
# Create a new Flower
|
65
|
+
rose = Flower.new
|
66
|
+
rose.name = "Red Rose"
|
67
|
+
rose.tags << "romantic" << "red"
|
68
|
+
rose.owners.push("Alice", "Bob")
|
69
|
+
rose.save
|
70
|
+
|
71
|
+
# Retrieve a Flower
|
72
|
+
retrieved_rose = Flower.get(rose.identifier)
|
73
|
+
puts retrieved_rose.name # => "Red Rose"
|
74
|
+
puts retrieved_rose.tags.members # => ["romantic", "red"]
|
27
75
|
```
|
28
76
|
|
29
77
|
## More Information
|
30
78
|
|
31
79
|
* [Github](https://github.com/delano/familia)
|
32
80
|
* [Rubygems](https://rubygems.org/gems/familia)
|
81
|
+
|
82
|
+
## Contributing
|
83
|
+
|
84
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
data/VERSION.yml
CHANGED
data/familia.gemspec
CHANGED
@@ -1,23 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'lib/familia/version'
|
4
|
+
|
1
5
|
Gem::Specification.new do |spec|
|
2
|
-
spec.name =
|
3
|
-
spec.version =
|
4
|
-
spec.summary =
|
6
|
+
spec.name = 'familia'
|
7
|
+
spec.version = Familia::VERSION.to_s
|
8
|
+
spec.summary = 'An ORM for Redis in Ruby.'
|
5
9
|
spec.description = "Familia: #{spec.summary}. Organize and store ruby objects in Redis"
|
6
|
-
spec.authors = [
|
7
|
-
spec.email =
|
8
|
-
spec.homepage =
|
9
|
-
spec.license =
|
10
|
+
spec.authors = ['Delano Mandelbaum']
|
11
|
+
spec.email = 'gems@solutious.com'
|
12
|
+
spec.homepage = 'https://github.com/delano/familia'
|
13
|
+
spec.license = 'MIT'
|
10
14
|
|
11
15
|
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
12
|
-
spec.bindir =
|
16
|
+
spec.bindir = 'exe'
|
13
17
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
14
|
-
spec.require_paths = [
|
18
|
+
spec.require_paths = ['lib']
|
15
19
|
|
16
|
-
spec.required_ruby_version = Gem::Requirement.new(
|
20
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.7.8')
|
17
21
|
|
18
22
|
spec.add_dependency 'redis', '>= 4.8.1', '< 6.0'
|
19
23
|
spec.add_dependency 'uri-redis', '~> 1.3'
|
20
|
-
|
21
|
-
|
22
|
-
spec.
|
24
|
+
|
25
|
+
# byebug only works with MRI
|
26
|
+
spec.add_development_dependency 'byebug', '~> 11.0' if RUBY_ENGINE == 'ruby'
|
27
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
23
28
|
end
|
data/lib/familia/base.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
module Familia
|
5
|
+
# A common module for Familia::RedisType and Familia::Horreum to include.
|
6
|
+
#
|
7
|
+
# This allows us to use a single comparison to check if a class is a
|
8
|
+
# Familia class. e.g.
|
9
|
+
#
|
10
|
+
# klass.include?(Familia::Base) # => true
|
11
|
+
# klass.ancestors.member?(Familia::Base) # => true
|
12
|
+
#
|
13
|
+
# @see Familia::Horreum
|
14
|
+
# @see Familia::RedisType
|
15
|
+
#
|
16
|
+
module Base
|
17
|
+
@features = nil
|
18
|
+
@dump_method = :to_json
|
19
|
+
@load_method = :from_json
|
20
|
+
|
21
|
+
class << self
|
22
|
+
attr_reader :features
|
23
|
+
attr_accessor :dump_method, :load_method
|
24
|
+
|
25
|
+
def add_feature(klass, methname)
|
26
|
+
@features ||= {}
|
27
|
+
Familia.ld "[#{self}] Adding feature #{klass} as #{methname}"
|
28
|
+
|
29
|
+
features[methname] = klass
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../../lib/redis_middleware'
|
4
|
+
|
5
|
+
#
|
6
|
+
module Familia
|
7
|
+
@uri = URI.parse 'redis://127.0.0.1'
|
8
|
+
@redis_clients = {}
|
9
|
+
|
10
|
+
# The Connection module provides Redis connection management for Familia.
|
11
|
+
# It allows easy setup and access to Redis clients across different URIs.
|
12
|
+
module Connection
|
13
|
+
# @return [Hash] A hash of Redis clients, keyed by server ID
|
14
|
+
attr_reader :redis_clients
|
15
|
+
|
16
|
+
# @return [URI] The default URI for Redis connections
|
17
|
+
attr_reader :uri
|
18
|
+
|
19
|
+
# @return [Boolean] Whether Redis command logging is enabled
|
20
|
+
attr_accessor :enable_redis_logging
|
21
|
+
|
22
|
+
# @return [Boolean] Whether Redis command counter is enabled
|
23
|
+
attr_accessor :enable_redis_counter
|
24
|
+
|
25
|
+
# Establishes a connection to a Redis server.
|
26
|
+
#
|
27
|
+
# @param uri [String, URI, nil] The URI of the Redis server to connect to.
|
28
|
+
# If nil, uses the default URI.
|
29
|
+
# @return [Redis] The connected Redis client
|
30
|
+
# @example
|
31
|
+
# Familia.connect('redis://localhost:6379')
|
32
|
+
def connect(uri = nil)
|
33
|
+
uri = URI.parse(uri) if uri.is_a?(String)
|
34
|
+
uri ||= Familia.uri
|
35
|
+
|
36
|
+
raise ArgumentError, 'No URI specified' unless uri
|
37
|
+
|
38
|
+
conf = uri.conf
|
39
|
+
|
40
|
+
if Familia.enable_redis_logging
|
41
|
+
RedisLogger.logger = Familia.logger
|
42
|
+
RedisClient.register(RedisLogger)
|
43
|
+
end
|
44
|
+
|
45
|
+
if Familia.enable_redis_counter
|
46
|
+
# NOTE: This middleware stays thread-safe with a mutex so it will
|
47
|
+
# be a bottleneck when enabled in multi-threaded environments.
|
48
|
+
RedisClient.register(RedisCommandCounter)
|
49
|
+
end
|
50
|
+
|
51
|
+
redis = Redis.new(conf)
|
52
|
+
@redis_clients[uri.serverid] = redis
|
53
|
+
end
|
54
|
+
|
55
|
+
# Retrieves or creates a Redis client for the given URI.
|
56
|
+
#
|
57
|
+
# @param uri [String, URI, nil] The URI of the Redis server.
|
58
|
+
# If nil, uses the default URI.
|
59
|
+
# @return [Redis] The Redis client for the specified URI
|
60
|
+
# @example
|
61
|
+
# Familia.redis('redis://localhost:6379')
|
62
|
+
def redis(uri = nil)
|
63
|
+
if uri.is_a?(Integer)
|
64
|
+
tmp = Familia.uri
|
65
|
+
tmp.db = uri
|
66
|
+
uri = tmp
|
67
|
+
elsif uri.is_a?(String)
|
68
|
+
uri &&= URI.parse uri
|
69
|
+
end
|
70
|
+
uri ||= Familia.uri
|
71
|
+
connect(uri) unless @redis_clients[uri.serverid]
|
72
|
+
@redis_clients[uri.serverid]
|
73
|
+
end
|
74
|
+
|
75
|
+
# Sets the default URI for Redis connections.
|
76
|
+
#
|
77
|
+
# @param v [String, URI] The new default URI
|
78
|
+
# @example
|
79
|
+
# Familia.uri = 'redis://localhost:6379'
|
80
|
+
def uri=(val)
|
81
|
+
@uri = val.is_a?(URI) ? v : URI.parse(val)
|
82
|
+
end
|
83
|
+
|
84
|
+
alias url uri
|
85
|
+
alias url= uri=
|
86
|
+
end
|
87
|
+
end
|