hoodoo 1.13.0 → 1.14.0

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