hoodoo 1.13.0 → 1.14.0

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.
Files changed (28) hide show
  1. checksums.yaml +4 -4
  2. data/lib/hoodoo.rb +1 -0
  3. data/lib/hoodoo/services/services/session.rb +8 -104
  4. data/lib/hoodoo/transient_store.rb +19 -0
  5. data/lib/hoodoo/transient_store/mocks/dalli_client.rb +148 -0
  6. data/lib/hoodoo/transient_store/mocks/redis.rb +138 -0
  7. data/lib/hoodoo/transient_store/transient_store.rb +344 -0
  8. data/lib/hoodoo/transient_store/transient_store/base.rb +81 -0
  9. data/lib/hoodoo/transient_store/transient_store/memcached.rb +116 -0
  10. data/lib/hoodoo/transient_store/transient_store/memcached_redis_mirror.rb +181 -0
  11. data/lib/hoodoo/transient_store/transient_store/redis.rb +126 -0
  12. data/lib/hoodoo/version.rb +1 -1
  13. data/spec/active/active_record/support_spec.rb +3 -9
  14. data/spec/active/active_record/translated_spec.rb +2 -5
  15. data/spec/logger/writers/file_writer_spec.rb +1 -4
  16. data/spec/logger/writers/stream_writer_spec.rb +2 -9
  17. data/spec/services/middleware/middleware_logging_spec.rb +1 -4
  18. data/spec/services/middleware/middleware_permissions_spec.rb +2 -2
  19. data/spec/services/services/interface_spec.rb +2 -2
  20. data/spec/services/services/session_spec.rb +26 -19
  21. data/spec/transient_store/transient_store/base_spec.rb +52 -0
  22. data/spec/transient_store/transient_store/memcached_redis_mirror_spec.rb +380 -0
  23. data/spec/transient_store/transient_store/memcached_spec.rb +244 -0
  24. data/spec/transient_store/transient_store/mocks/dalli_client_spec.rb +44 -0
  25. data/spec/transient_store/transient_store/mocks/redis_spec.rb +28 -0
  26. data/spec/transient_store/transient_store/redis_spec.rb +242 -0
  27. data/spec/transient_store/transient_store_spec.rb +448 -0
  28. metadata +31 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7afd9823b45dd59e8031b83a8eafe26118d38240
4
- data.tar.gz: 3b23639744e3b536f5f5192538e88d07cf7cccef
3
+ metadata.gz: 5f2eb0d49452cfe11be6f7953e2915139a799389
4
+ data.tar.gz: 2d9ca68a6fc2f064c7e8c1a3473ef3028369ff02
5
5
  SHA512:
6
- metadata.gz: 79d4a1cc3b9217baecf9129b245e16fea79d80f0fd8cf1accc54724e43ec9d9ea0fc4988241ba5418d52c8c5f33b401fad4157db204e2adfcf8bac72ba69a9e6
7
- data.tar.gz: 0bd7649d997eec9b349119464bcd6ea801ffd099bf0df21136e77a6401449cf045f8cd931d0a9846afcc5beb9be02f063643115bde2054de46ddbb5e8acd6766
6
+ metadata.gz: a3091aedf879cae316a5bbf757bca8f6a01967bd41608359d7ab01f8b54330d2faf482ac0d5d80e222d88ffa9425d15fec98e02e6c976aa9223adbd1ff536816
7
+ data.tar.gz: 2194d4e534790c220d2bdfadc2b9efc42a8ba408741b1933a6f0c66edd47e2e40103aa04a6a7a22e66e78576395d035a70e111425aad4c0bf59030590ff50019
data/lib/hoodoo.rb CHANGED
@@ -13,6 +13,7 @@ module Hoodoo
13
13
  end
14
14
 
15
15
  require 'hoodoo/utilities'
16
+ require 'hoodoo/transient_store'
16
17
  require 'hoodoo/communicators'
17
18
  require 'hoodoo/logger'
18
19
  require 'hoodoo/presenters'
@@ -10,6 +10,7 @@
10
10
 
11
11
  require 'ostruct'
12
12
  require 'dalli'
13
+ require 'hoodoo/transient_store/mocks/dalli_client'
13
14
 
14
15
  module Hoodoo
15
16
  module Services
@@ -634,111 +635,14 @@ module Hoodoo
634
635
  )
635
636
  end
636
637
 
637
- # Mock known uses of Dalli::Client with test implementations.
638
- # Use explicitly, or as an RSpec implicit mock via something like
639
- # this:
638
+ # Before Hoodoo::TransientStore was created, the Session system was
639
+ # directly tied into Memcached and had a mock backend used for tests
640
+ # without a Redis dependency. This now lives in
641
+ # Hoodoo::TransientStore::Mocks::DalliClient, but for any code out in
642
+ # the wild which might use the old Session namespace version, we add
643
+ # what amounts to a class alias here.
640
644
  #
641
- # allow( Dalli::Client ).to receive( :new ).and_return( Hoodoo::Services::Session::MockDalliClient.new )
642
- #
643
- # ...whenever you need to stub out real Memcached. You will
644
- # probably want to add:
645
- #
646
- # before :all do # (or ":each")
647
- # Hoodoo::Services::Session::MockDalliClient.reset()
648
- # end
649
- #
650
- # ...to "clean out Memcached" before or between tests. You can
651
- # check the contents of mock Memcached by examining ::store's
652
- # hash of data.
653
- #
654
- class MockDalliClient
655
- @@store = {}
656
-
657
- # For test analysis, return the hash of 'memcached' mock data.
658
- #
659
- # Entries are referenced by the key you used to originally
660
- # store them; values are hashes with ":expires_at" giving an
661
- # expiry time or "nil" and ":value" giving your stored value.
662
- #
663
- def self.store
664
- @@store
665
- end
666
-
667
- # Wipe out all saved data.
668
- #
669
- def self.reset
670
- @@store = {}
671
- end
672
-
673
- # Pass +true+ to bypass the mock client (subject to the caller
674
- # reading ::bypass?) to e.g. get test code coverage on real
675
- # Memcached. Pass +false+ otherwise.
676
- #
677
- def self.bypass( bypass_boolean )
678
- @@bypass = bypass_boolean
679
- end
680
-
681
- @@bypass = false
682
-
683
- # If +true+, bypass this class and use real Dalli::Client; else
684
- # don't. Default return value is +false+.
685
- #
686
- def self.bypass?
687
- @@bypass
688
- end
689
-
690
- # Get the data stored under the given key. Returns +nil+ if
691
- # not found / expired.
692
- #
693
- # +key+:: Key to look up (see #set).
694
- #
695
- def get( key )
696
- data = @@store[ key ]
697
- return nil if data.nil?
698
-
699
- expires_at = data[ :expires_at ]
700
- return nil unless expires_at.nil? || Time.now < expires_at
701
-
702
- return data[ :value ]
703
- end
704
-
705
- # Set data for a given key.
706
- #
707
- # +key+:: Key under which to store data.
708
- #
709
- # +value+:: Data to store.
710
- #
711
- # +ttl+:: (Optional) time-to-live ('live' as in living, not as in
712
- # 'live TV') - a value in seconds, after which the data is
713
- # considered expired. If omitted, the data does not expire.
714
- #
715
- def set( key, value, ttl = nil )
716
- data = {
717
- :expires_at => ttl.nil? ? nil : Time.now.utc + ttl,
718
- :value => value
719
- }
720
-
721
- @@store[ key ] = data
722
- true
723
- end
724
-
725
- # Remove data for the given key.
726
- #
727
- def delete( key )
728
- if @@store.has_key?( key )
729
- @@store.delete( key )
730
- true
731
- else
732
- false
733
- end
734
- end
735
-
736
- # Mock 'stats' health check.
737
- #
738
- def stats
739
- true
740
- end
741
- end
645
+ MockDalliClient = Hoodoo::TransientStore::Mocks::DalliClient
742
646
  end
743
647
  end
744
648
  end
@@ -0,0 +1,19 @@
1
+ ########################################################################
2
+ # File:: transient_store.rb
3
+ # (C):: Loyalty New Zealand 2017
4
+ #
5
+ # Purpose:: Include temporary/transient storage abstraction layers.
6
+ # ----------------------------------------------------------------------
7
+ # 01-Feb-2017 (ADH): Created
8
+ ########################################################################
9
+
10
+ # Core abstraction
11
+
12
+ require 'hoodoo/transient_store/transient_store'
13
+ require 'hoodoo/transient_store/transient_store/base'
14
+
15
+ # Storage engine plugins
16
+
17
+ require 'hoodoo/transient_store/transient_store/memcached'
18
+ require 'hoodoo/transient_store/transient_store/redis'
19
+ require 'hoodoo/transient_store/transient_store/memcached_redis_mirror'
@@ -0,0 +1,148 @@
1
+ ########################################################################
2
+ # File:: dalli_client.rb
3
+ # (C):: Loyalty New Zealand 2017
4
+ #
5
+ # Purpose:: A mock/fake Dalli::Client minimal implementation as an
6
+ # alternative test back-end for Memcached-independent tests.
7
+ # ----------------------------------------------------------------------
8
+ # 02-Feb-2017 (ADH): Created.
9
+ ########################################################################
10
+
11
+ module Hoodoo
12
+ class TransientStore
13
+
14
+ # Mock back-end code used by tests to allow them to run without a
15
+ # dependency on the real engine (though the real engine is always
16
+ # recommended and Hoodoo core tests always cover both).
17
+ #
18
+ class Mocks
19
+
20
+ # Mock known uses of Dalli::Client with test implementations.
21
+ # Use explicitly, or as an RSpec implicit mock via something like
22
+ # this:
23
+ #
24
+ # allow( Dalli::Client ).to(
25
+ # receive( :new ).
26
+ # and_return( Hoodoo::TransientStore::Mocks::DalliClient.new )
27
+ # )
28
+ #
29
+ # ...whenever you need to stub out real Memcached. You will
30
+ # probably want to add:
31
+ #
32
+ # before :all do # (or ":each")
33
+ # Hoodoo::TransientStore::Mocks::DalliClient.reset()
34
+ # end
35
+ #
36
+ # ...to "clean out Memcached" before or between tests. You can
37
+ # check the contents of mock Memcached by examining ::store's
38
+ # hash of data.
39
+ #
40
+ # The test coverage for Hoodoo::TransientStore selects this backend in
41
+ # passing. Generally speaking you should favour Hoodoo::TransientStore
42
+ # over hard-coding to a storage engine available by the Hoodoo
43
+ # abstraction and, as a result, may never need this mock class at all.
44
+ #
45
+ class DalliClient
46
+ @@store = {}
47
+
48
+ # For test analysis, return the hash of 'memcached' mock data.
49
+ #
50
+ # Entries are referenced by the key you used to originally
51
+ # store them; values are hashes with ":expires_at" giving an
52
+ # expiry time or "nil" and ":value" giving your stored value.
53
+ #
54
+ def self.store
55
+ @@store
56
+ end
57
+
58
+ # Wipe out all saved data.
59
+ #
60
+ def self.reset
61
+ @@store = {}
62
+ end
63
+
64
+ # Pass +true+ to bypass the mock client (subject to the caller
65
+ # reading ::bypass?) to e.g. get test code coverage on real
66
+ # Memcached. Pass +false+ otherwise.
67
+ #
68
+ # (Deprecated, but indefinitely maintained).
69
+ #
70
+ def self.bypass( bypass_boolean )
71
+ @@bypass = bypass_boolean
72
+ end
73
+
74
+ @@bypass = false
75
+
76
+ # If +true+, bypass this class and use real Dalli::Client; else
77
+ # don't. Default return value is +false+.
78
+ #
79
+ # (Deprecated, but indefinitely maintained).
80
+ #
81
+ def self.bypass?
82
+ @@bypass
83
+ end
84
+
85
+ # Get the data stored under the given key. Returns +nil+ if
86
+ # not found / expired.
87
+ #
88
+ # +key+:: Key to look up (see #set).
89
+ #
90
+ def get( key )
91
+ data = @@store[ key ]
92
+ return nil if data.nil?
93
+
94
+ expires_at = data[ :expires_at ]
95
+ return nil unless expires_at.nil? || Time.now < expires_at
96
+
97
+ return data[ :value ]
98
+ end
99
+
100
+ # Set data for a given key.
101
+ #
102
+ # +key+:: Key under which to store data.
103
+ #
104
+ # +value+:: Data to store.
105
+ #
106
+ # +ttl+:: (Optional) time-to-live ('live' as in living, not as in
107
+ # 'live TV') - a value in seconds, after which the data is
108
+ # considered expired. If omitted, the data does not expire.
109
+ #
110
+ def set( key, value, ttl = nil )
111
+ data = {
112
+ :expires_at => ttl.nil? ? nil : Time.now.utc + ttl,
113
+ :value => value
114
+ }
115
+
116
+ @@store[ key ] = data
117
+ true
118
+ end
119
+
120
+ # Remove data for the given key.
121
+ #
122
+ def delete( key )
123
+ if @@store.has_key?( key )
124
+ @@store.delete( key )
125
+ true
126
+ else
127
+ false
128
+ end
129
+ end
130
+
131
+ # Stub for 'closing' a connection.
132
+ #
133
+ def close; end
134
+
135
+ # Mock 'stats' health check.
136
+ #
137
+ def stats
138
+
139
+ # Should really be a Hash, but kept as 'true' in case any existing
140
+ # client depends on this; it isn't too important either way.
141
+ #
142
+ true
143
+
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,138 @@
1
+ ########################################################################
2
+ # File:: redis.rb
3
+ # (C):: Loyalty New Zealand 2017
4
+ #
5
+ # Purpose:: A mock/fake Redis client minimal implementation as an
6
+ # alternative test back-end for Redis-independent tests.
7
+ # ----------------------------------------------------------------------
8
+ # 02-Feb-2017 (ADH): Created.
9
+ ########################################################################
10
+
11
+ module Hoodoo
12
+ class TransientStore
13
+ class Mocks
14
+
15
+ # Mock known uses of Redis with test implementations. Use explicitly,
16
+ # or as an RSpec implicit mock via something like this:
17
+ #
18
+ # allow( Redis ).to(
19
+ # receive( :new ).
20
+ # and_return( Hoodoo::TransientStore::Mocks::Redis.new )
21
+ # )
22
+ #
23
+ # ...whenever you need to stub out real Memcached. You will
24
+ # probably want to add:
25
+ #
26
+ # before :all do # (or ":each")
27
+ # Hoodoo::TransientStore::Mocks::Redis.reset()
28
+ # end
29
+ #
30
+ # ...to "clean out Memcached" before or between tests. You can
31
+ # check the contents of mock Memcached by examining ::store's
32
+ # hash of data.
33
+ #
34
+ # The test coverage for Hoodoo::TransientStore selects this backend in
35
+ # passing. Generally speaking you should favour Hoodoo::TransientStore
36
+ # over hard-coding to a storage engine available by the Hoodoo
37
+ # abstraction and, as a result, may never need this mock class at all.
38
+ #
39
+ class Redis
40
+ @@store = {}
41
+
42
+ # For test analysis, return the hash of 'memcached' mock data.
43
+ #
44
+ # Entries are referenced by the key you used to originally
45
+ # store them; values are hashes with ":expires_at" giving an
46
+ # expiry time or "nil" and ":value" giving your stored value.
47
+ #
48
+ def self.store
49
+ @@store
50
+ end
51
+
52
+ # Wipe out all saved data.
53
+ #
54
+ def self.reset
55
+ @@store = {}
56
+ end
57
+
58
+ # Get the data stored under the given key. Returns +nil+ if
59
+ # not found / expired.
60
+ #
61
+ # +key+:: Key to look up (see #set).
62
+ #
63
+ def get( key )
64
+ data = @@store[ key ]
65
+ return nil if data.nil?
66
+
67
+ expires_at = data[ :expires_at ]
68
+ return nil unless expires_at.nil? || Time.now < expires_at
69
+
70
+ return data[ :value ]
71
+ end
72
+
73
+ # Alias for #get.
74
+ #
75
+ def []( key )
76
+ get( key )
77
+ end
78
+
79
+ # Set data for a given key.
80
+ #
81
+ # +key+:: Key under which to store data.
82
+ #
83
+ # +value+:: Data to store.
84
+ #
85
+ # +ttl+:: (Optional) time-to-live ('live' as in living, not as in
86
+ # 'live TV') - a value in seconds, after which the data is
87
+ # considered expired. If omitted, the data does not expire.
88
+ #
89
+ def set( key, value, ttl = nil )
90
+ @@store[ key ] = { :value => value }
91
+ 'OK'
92
+ end
93
+
94
+ # Alias for #set.
95
+ #
96
+ def []=( key, value )
97
+ set( key, value )
98
+ end
99
+
100
+ # Set expiry time for a given key, which must exist.
101
+ #
102
+ # +ttl+:: time-to-live ('live' as in living, not as in 'live TV').
103
+ # A value in seconds, after which the data is considered
104
+ # expired.
105
+ #
106
+ def expire( key, ttl )
107
+ unless @@store.has_key?( key )
108
+ raise "Hoodoo::TransientStore::Mocks::Redis\#expire: Cannot find key '#{ key }'"
109
+ end
110
+
111
+ @@store[ key ][ :expires_at ] = Time.now.utc + ttl
112
+ true
113
+ end
114
+
115
+ # Remove data for the given key.
116
+ #
117
+ def del( key )
118
+ if @@store.has_key?( key )
119
+ @@store.delete( key )
120
+ 1
121
+ else
122
+ 0
123
+ end
124
+ end
125
+
126
+ # Stub for 'closing' a connection.
127
+ #
128
+ def quit; end
129
+
130
+ # Mock 'info' health check.
131
+ #
132
+ def info( command )
133
+ { :alive => command }
134
+ end
135
+ end
136
+ end
137
+ end
138
+ end