momento 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.release-please-manifest.json +3 -0
  3. data/.rubocop.yml +12 -0
  4. data/.yardopts +2 -0
  5. data/CHANGELOG.md +28 -0
  6. data/CONTRIBUTING.md +1 -1
  7. data/Gemfile.lock +7 -3
  8. data/README.md +131 -36
  9. data/README.template.md +88 -0
  10. data/examples/.gitignore +1 -0
  11. data/examples/Gemfile +5 -0
  12. data/examples/README.md +34 -0
  13. data/examples/compact.rb +43 -0
  14. data/examples/example.rb +66 -0
  15. data/examples/file.rb +57 -0
  16. data/lib/momento/cacheclient_pb.rb +2 -0
  17. data/lib/momento/cacheclient_services_pb.rb +2 -0
  18. data/lib/momento/controlclient_pb.rb +2 -0
  19. data/lib/momento/controlclient_services_pb.rb +2 -0
  20. data/lib/momento/create_cache_response.rb +9 -24
  21. data/lib/momento/create_cache_response_builder.rb +27 -0
  22. data/lib/momento/delete_cache_response.rb +6 -21
  23. data/lib/momento/delete_cache_response_builder.rb +25 -0
  24. data/lib/momento/delete_response.rb +6 -15
  25. data/lib/momento/delete_response_builder.rb +23 -0
  26. data/lib/momento/error/grpc_details.rb +38 -0
  27. data/lib/momento/error/transport_details.rb +20 -0
  28. data/lib/momento/error/types.rb +232 -0
  29. data/lib/momento/error.rb +54 -0
  30. data/lib/momento/error_builder.rb +50 -0
  31. data/lib/momento/exceptions.rb +7 -0
  32. data/lib/momento/get_response.rb +37 -40
  33. data/lib/momento/get_response_builder.rb +37 -0
  34. data/lib/momento/list_caches_response.rb +45 -21
  35. data/lib/momento/list_caches_response_builder.rb +25 -0
  36. data/lib/momento/response/error.rb +10 -3
  37. data/lib/momento/response.rb +54 -1
  38. data/lib/momento/response_builder.rb +18 -0
  39. data/lib/momento/set_response.rb +21 -21
  40. data/lib/momento/set_response_builder.rb +25 -0
  41. data/lib/momento/simple_cache_client.rb +163 -31
  42. data/lib/momento/ttl.rb +48 -0
  43. data/lib/momento/version.rb +2 -1
  44. data/momento.gemspec +1 -0
  45. data/release-please-config.json +15 -0
  46. metadata +44 -6
  47. data/examples/basic.rb +0 -45
@@ -1,50 +1,35 @@
1
- require 'grpc'
2
- require 'momento/controlclient_pb'
1
+ require_relative 'response/error'
3
2
 
4
3
  module Momento
5
- # Responses specific to create_cache.
4
+ # A response from creating a cache.
6
5
  class CreateCacheResponse < Response
7
- # Build a Momento::CreateCacheResponse from a block of code
8
- # which returns a Momento::ControlClient::CreateCacheResponse.
9
- #
10
- # @return [Momento::CreateCacheResponse]
11
- # @raise [StandardError] when the exception is not recognized.
12
- # @raise [TypeError] when the response is not recognized.
13
- def self.from_block
14
- response = yield
15
- rescue GRPC::AlreadyExists
16
- return AlreadyExists.new
17
- rescue GRPC::BadStatus => e
18
- Error.new(grpc_exception: e)
19
- else
20
- raise TypeError unless response.is_a?(Momento::ControlClient::CreateCacheResponse)
21
-
22
- return Success.new
23
- end
24
-
6
+ # Does the cache already exist?
7
+ # @return [Boolean]
25
8
  def already_exists?
26
9
  false
27
10
  end
28
11
 
12
+ # Was the cache created?
13
+ # @return [Boolean]
29
14
  def success?
30
15
  false
31
16
  end
32
17
 
33
- # A cache with that name already exists.
18
+ # @private
34
19
  class AlreadyExists < CreateCacheResponse
35
20
  def already_exists?
36
21
  true
37
22
  end
38
23
  end
39
24
 
40
- # The cache was created.
25
+ # @private
41
26
  class Success < CreateCacheResponse
42
27
  def success?
43
28
  true
44
29
  end
45
30
  end
46
31
 
47
- # There was an error creating the cache.
32
+ # @private
48
33
  class Error < CreateCacheResponse
49
34
  include ::Momento::Response::Error
50
35
  end
@@ -0,0 +1,27 @@
1
+ require 'grpc'
2
+ require_relative 'controlclient_pb'
3
+
4
+ module Momento
5
+ # @private
6
+ class CreateCacheResponseBuilder < ResponseBuilder
7
+ # Build a Momento::CreateCacheResponse from a block of code
8
+ # which returns a Momento::ControlClient::CreateCacheResponse.
9
+ #
10
+ # @return [Momento::CreateCacheResponse]
11
+ # @raise [StandardError] when the exception is not recognized.
12
+ # @raise [TypeError] when the response is not recognized.
13
+ def from_block
14
+ response = yield
15
+ rescue GRPC::AlreadyExists
16
+ return CreateCacheResponse::AlreadyExists.new
17
+ rescue *RESCUED_EXCEPTIONS => e
18
+ CreateCacheResponse::Error.new(
19
+ exception: e, context: context
20
+ )
21
+ else
22
+ raise TypeError unless response.is_a?(::Momento::ControlClient::CreateCacheResponse)
23
+
24
+ return CreateCacheResponse::Success.new
25
+ end
26
+ end
27
+ end
@@ -1,35 +1,20 @@
1
- require 'grpc'
2
- require 'momento/controlclient_pb'
1
+ require_relative 'response/error'
3
2
 
4
3
  module Momento
5
- # Responses specific to delete_cache
4
+ # A response from deleting a cache.
6
5
  class DeleteCacheResponse < Response
7
- # Build a Momento::DeleteCacheResponse from a block of code
8
- # which returns a Momento::ControlClient::DeleteCacheResponse..
9
- #
10
- # @return [Momento::DeleteCacheResponse]
11
- # @raise [StandardError] when the exception is not recognized.
12
- # @raise [TypeError] when the response is not recognized.
13
- def self.from_block
14
- response = yield
15
- rescue GRPC::BadStatus => e
16
- Error.new(grpc_exception: e)
17
- else
18
- raise TypeError unless response.is_a?(Momento::ControlClient::DeleteCacheResponse)
19
-
20
- return Success.new
21
- end
22
-
6
+ # Was the cache deleted?
7
+ # @return [Boolean]
23
8
  def success?
24
9
  false
25
10
  end
26
11
 
27
- # There was an error deleting the cache.
12
+ # @private
28
13
  class Error < DeleteCacheResponse
29
14
  include ::Momento::Response::Error
30
15
  end
31
16
 
32
- # The cache was deleted.
17
+ # @private
33
18
  class Success < DeleteCacheResponse
34
19
  def success?
35
20
  true
@@ -0,0 +1,25 @@
1
+ require 'grpc'
2
+ require_relative 'controlclient_pb'
3
+
4
+ module Momento
5
+ # @private
6
+ class DeleteCacheResponseBuilder < ResponseBuilder
7
+ # Build a Momento::DeleteCacheResponse from a block of code
8
+ # which returns a Momento::ControlClient::DeleteCacheResponse..
9
+ #
10
+ # @return [Momento::DeleteCacheResponse]
11
+ # @raise [StandardError] when the exception is not recognized.
12
+ # @raise [TypeError] when the response is not recognized.
13
+ def from_block
14
+ response = yield
15
+ rescue *RESCUED_EXCEPTIONS => e
16
+ DeleteCacheResponse::Error.new(
17
+ exception: e, context: context
18
+ )
19
+ else
20
+ raise TypeError unless response.is_a?(::Momento::ControlClient::DeleteCacheResponse)
21
+
22
+ return DeleteCacheResponse::Success.new
23
+ end
24
+ end
25
+ end
@@ -1,31 +1,22 @@
1
- require 'grpc'
2
- require 'momento/cacheclient_pb'
1
+ require_relative 'response/error'
3
2
 
4
3
  module Momento
5
- # Responses specific to delete.
4
+ # A response from deleting a key.
6
5
  class DeleteResponse < Response
7
- def self.from_block
8
- response = yield
9
- rescue GRPC::BadStatus => e
10
- Error.new(grpc_exception: e)
11
- else
12
- raise TypeError unless response.is_a?(Momento::CacheClient::DeleteResponse)
13
-
14
- Success.new
15
- end
16
-
6
+ # Was the key deleted?
7
+ # @return [Boolean]
17
8
  def success?
18
9
  false
19
10
  end
20
11
 
21
- # The item was deleted from the cache.
12
+ # @private
22
13
  class Success < DeleteResponse
23
14
  def success?
24
15
  true
25
16
  end
26
17
  end
27
18
 
28
- # There was an error deleting the item from the cache.
19
+ # @private
29
20
  class Error < DeleteResponse
30
21
  include Momento::Response::Error
31
22
  end
@@ -0,0 +1,23 @@
1
+ require 'grpc'
2
+ require_relative 'cacheclient_pb'
3
+
4
+ module Momento
5
+ # @private
6
+ class DeleteResponseBuilder < ResponseBuilder
7
+ # Build a Momento::DeleteResponse from a block of code
8
+ # which returns a Momento::CacheClient::DeleteResponse..
9
+ #
10
+ # @return [Momento::DeleteResponse]
11
+ # @raise [StandardError] when the exception is not recognized.
12
+ # @raise [TypeError] when the response is not recognized.
13
+ def from_block
14
+ response = yield
15
+ rescue *RESCUED_EXCEPTIONS => e
16
+ DeleteResponse::Error.new(exception: e, context: context)
17
+ else
18
+ raise TypeError unless response.is_a?(::Momento::CacheClient::DeleteResponse)
19
+
20
+ DeleteResponse::Success.new
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,38 @@
1
+ module Momento
2
+ module Error
3
+ # Details about a GRPC error.
4
+ # Returned by `response.error.transport_details.grpc`
5
+ #
6
+ # @example
7
+ # # Information about the underlying GRPC error which
8
+ # # caused a Momento error response.
9
+ # puts response.error.transport_details.grpc.details
10
+ class GrpcDetails
11
+ # @return [GRPC::BadStatus] the GRPC exception
12
+ attr_reader :grpc
13
+
14
+ # @param grpc [GRPC::BadStatus] the GRPC exception to wrap
15
+ def initialize(grpc)
16
+ @grpc = grpc
17
+ end
18
+
19
+ # The GRPC numeric error code
20
+ # @return [Integer]
21
+ def code
22
+ grpc.code
23
+ end
24
+
25
+ # Any details about the error provided by GRPC
26
+ # @return [String]
27
+ def details
28
+ grpc.details
29
+ end
30
+
31
+ # Any metadata associated with the GRPC error
32
+ # @return [Hash]
33
+ def metadata
34
+ grpc.metadata
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,20 @@
1
+ module Momento
2
+ module Error
3
+ # A class to capture information specific to particular transport layers.
4
+ #
5
+ # @example
6
+ # # Information about the underlying GRPC error which
7
+ # # caused a Momento error response.
8
+ # puts response.error.transport_details.grpc.details
9
+ class TransportDetails
10
+ # Details specific to GRPC.
11
+ # @return [Momento::Error::GrpcDetails]
12
+ attr_reader :grpc
13
+
14
+ # param grpc [GRPC::BadStatus]
15
+ def initialize(grpc:)
16
+ @grpc = GrpcDetails.new(grpc)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,232 @@
1
+ module Momento
2
+ module Error
3
+ # rubocop:disable Layout/LineLength
4
+
5
+ # A cache with the specified name already exists.
6
+ class AlreadyExistsError < RuntimeError
7
+ include Momento::Error
8
+
9
+ # (see Momento::Error#error_code)
10
+ def error_code
11
+ :ALREADY_EXISTS_ERROR
12
+ end
13
+
14
+ # (see Momento::Error#message)
15
+ def message
16
+ "A cache with the specified name already exists. To resolve this error, either delete the existing cache and make a new one, or use a different name. Cache name: '#{context[:cache_name]}'"
17
+ end
18
+ end
19
+
20
+ # Invalid authentication credentials to connect to cache service
21
+ class AuthenticationError < RuntimeError
22
+ include Momento::Error
23
+
24
+ # (see Momento::Error#error_code)
25
+ def error_code
26
+ :AUTHENTICATION_ERROR
27
+ end
28
+
29
+ # (see Momento::Error#message)
30
+ def message
31
+ "Invalid authentication credentials to connect to cache service: #{details}"
32
+ end
33
+ end
34
+
35
+ # The request was invalid.
36
+ class BadRequestError < RuntimeError
37
+ include Momento::Error
38
+
39
+ # (see Momento::Error#error_code)
40
+ def error_code
41
+ :BAD_REQUEST_ERROR
42
+ end
43
+
44
+ # (see Momento::Error#message)
45
+ def message
46
+ "The request was invalid; please contact Momento: #{details}"
47
+ end
48
+ end
49
+
50
+ # The request was cancelled by the server.
51
+ class CancelledError < RuntimeError
52
+ include Momento::Error
53
+
54
+ # (see Momento::Error#error_code)
55
+ def error_code
56
+ :CANCELLED_ERROR
57
+ end
58
+
59
+ # (see Momento::Error#message)
60
+ def message
61
+ "The request was cancelled by the server; please contact Momento: #{details}"
62
+ end
63
+ end
64
+
65
+ # A client resource (most likely memory) was exhausted.
66
+ class ClientResourceExhaustedError < RuntimeError
67
+ include Momento::Error
68
+
69
+ # (see Momento::Error#error_code)
70
+ def error_code
71
+ :CLIENT_RESOURCE_EXHAUSTED
72
+ end
73
+
74
+ # (see Momento::Error#message)
75
+ def message
76
+ "A client resource (most likely memory) was exhausted. If you are executing a high volume of concurrent requests or using very large object sizes, your Configuration may need to be updated to allocate more memory. Please contact Momento for assistance."
77
+ end
78
+ end
79
+
80
+ # System is not in a state required for the operation\'s execution
81
+ class FailedPreconditionError < RuntimeError
82
+ include Momento::Error
83
+
84
+ # (see Momento::Error#error_code)
85
+ def error_code
86
+ :FAILED_PRECONDITION_ERROR
87
+ end
88
+
89
+ # (see Momento::Error#message)
90
+ def message
91
+ "System is not in a state required for the operation's execution"
92
+ end
93
+ end
94
+
95
+ # An unexpected error occurred while trying to fulfill the request.
96
+ class InternalServerError < RuntimeError
97
+ include Momento::Error
98
+
99
+ # (see Momento::Error#error_code)
100
+ def error_code
101
+ :INTERNAL_SERVER_ERROR
102
+ end
103
+
104
+ # (see Momento::Error#message)
105
+ def message
106
+ "An unexpected error occurred while trying to fulfill the request; please contact Momento: #{details}"
107
+ end
108
+ end
109
+
110
+ # Invalid argument passed to Momento client
111
+ class InvalidArgumentError < ArgumentError
112
+ include Momento::Error
113
+
114
+ # (see Momento::Error#error_code)
115
+ def error_code
116
+ :INVALID_ARGUMENT_ERROR
117
+ end
118
+
119
+ # (see Momento::Error#message)
120
+ def message
121
+ "Invalid argument passed to Momento client: #{details}"
122
+ end
123
+ end
124
+
125
+ # Request rate exceeded the limits for this account.
126
+ class LimitExceededError < RuntimeError
127
+ include Momento::Error
128
+
129
+ # (see Momento::Error#error_code)
130
+ def error_code
131
+ :LIMIT_EXCEEDED_ERROR
132
+ end
133
+
134
+ # (see Momento::Error#message)
135
+ def message
136
+ "Request rate exceeded the limits for this account. To resolve this error, reduce your request rate, or contact Momento to request a limit increase."
137
+ end
138
+ end
139
+
140
+ # A cache with the specified name does not exist.
141
+ class NotFoundError < RuntimeError
142
+ include Momento::Error
143
+
144
+ # (see Momento::Error#error_code)
145
+ def error_code
146
+ :NOT_FOUND_ERROR
147
+ end
148
+
149
+ # (see Momento::Error#message)
150
+ def message
151
+ "A cache with the specified name does not exist. To resolve this error, make sure you have created the cache before attempting to use it. Cache name: '#{context[:cache_name]}'"
152
+ end
153
+ end
154
+
155
+ # Insufficient permissions to perform an operation on a cache.
156
+ class PermissionError < RuntimeError
157
+ include Momento::Error
158
+
159
+ # (see Momento::Error#error_code)
160
+ def error_code
161
+ :PERMISSION_ERROR
162
+ end
163
+
164
+ # (see Momento::Error#message)
165
+ def message
166
+ "Insufficient permissions to perform an operation on a cache: #{details}"
167
+ end
168
+ end
169
+
170
+ # The server was unable to handle the request
171
+ class ServerUnavailableError < RuntimeError
172
+ include Momento::Error
173
+
174
+ # (see Momento::Error#error_code)
175
+ def error_code
176
+ :SERVER_UNAVAILABLE
177
+ end
178
+
179
+ # (see Momento::Error#message)
180
+ def message
181
+ "The server was unable to handle the request; consider retrying. If the error persists, please contact Momento."
182
+ end
183
+ end
184
+
185
+ # The client's configured timeout was exceeded.
186
+ class TimeoutError < RuntimeError
187
+ include Momento::Error
188
+
189
+ # (see Momento::Error#error_code)
190
+ def error_code
191
+ :TIMEOUT_ERROR
192
+ end
193
+
194
+ # (see Momento::Error#message)
195
+ def message
196
+ "The client's configured timeout was exceeded; you may need to use a Configuration with more lenient timeouts. Timeout value: #{context[:timeout]}"
197
+ end
198
+ end
199
+
200
+ # The cache service failed due to an internal error
201
+ class UnknownError < RuntimeError
202
+ include Momento::Error
203
+
204
+ # (see Momento::Error#error_code)
205
+ def error_code
206
+ :UNKNOWN_ERROR
207
+ end
208
+
209
+ # (see Momento::Error#message)
210
+ def message
211
+ "CacheService failed due to an internal error"
212
+ end
213
+ end
214
+
215
+ # The cache service failed due to an internal error
216
+ class UnknownServiceError < RuntimeError
217
+ include Momento::Error
218
+
219
+ # (see Momento::Error#error_code)
220
+ def error_code
221
+ :UNKNOWN_SERVICE_ERROR
222
+ end
223
+
224
+ # (see Momento::Error#message)
225
+ def message
226
+ "The service returned an unknown response; please contact Momento: #{details}"
227
+ end
228
+ end
229
+
230
+ # rubocop:enable Layout/LineLength
231
+ end
232
+ end
@@ -0,0 +1,54 @@
1
+ require_relative 'error/types'
2
+
3
+ module Momento
4
+ # Errors from the Momento client or service, available as `response.error`.
5
+ #
6
+ # Momento::Errors are Exceptions. They can be raised. If the error was
7
+ # caused by an exception, it will be available in {#cause}.
8
+ #
9
+ # @example
10
+ # # This is a contrived example to show what you can do with a Momento::Error.
11
+ # response = client.cache_name(cache_name, key)
12
+ # if response.error?
13
+ # error = response.error
14
+ #
15
+ # puts "Creating the cache failed: #{error}"
16
+ # puts "The cause was #{error.cause}"
17
+ # puts "The details of the error are #{error.details}"
18
+ # puts "The error code is #{error.error_code}"
19
+ #
20
+ # case error
21
+ # when Momento::Error::LimitExceededError
22
+ # puts "We'll have to slow down"
23
+ # when Momento::Error::PermissionError
24
+ # puts "We'll have to fix our auth token"
25
+ # when Momento::Error::InvalidArgumentError
26
+ # puts "We can't make a cache named #{cache_name}"
27
+ # end
28
+ #
29
+ # raise error
30
+ # end
31
+ module Error
32
+ # @return [Exception] the original exception which was the cause of the error
33
+ attr_accessor :cause
34
+ # @return [Hash] any context relevant to the error such as method arguments
35
+ attr_accessor :context
36
+ # @return [Momento::Error::TransportDetails] details about the transport layer
37
+ attr_accessor :transport_details
38
+ # @return [String] details about the error
39
+ attr_accessor :details
40
+
41
+ # @!method error_code
42
+ # A Momento-specific code for the type of error.
43
+ # @return [Symbol]
44
+
45
+ # @!method message
46
+ # The error message.
47
+ # @return [String]
48
+
49
+ # (see #message)
50
+ def to_s
51
+ message
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,50 @@
1
+ require 'grpc'
2
+ require_relative 'error/types'
3
+ require_relative 'exceptions'
4
+
5
+ module Momento
6
+ # @private
7
+ class ErrorBuilder
8
+ EXCEPTION_MAP = {
9
+ GRPC::Aborted => Error::InternalServerError,
10
+ GRPC::AlreadyExists => Error::AlreadyExistsError,
11
+ GRPC::Cancelled => Error::CancelledError,
12
+ GRPC::DataLoss => Error::InternalServerError,
13
+ GRPC::DeadlineExceeded => Error::TimeoutError,
14
+ GRPC::FailedPrecondition => Error::FailedPreconditionError,
15
+ GRPC::Internal => Error::InternalServerError,
16
+ GRPC::InvalidArgument => Error::InvalidArgumentError,
17
+ GRPC::NotFound => Error::NotFoundError,
18
+ GRPC::OutOfRange => Error::BadRequestError,
19
+ GRPC::PermissionDenied => Error::PermissionError,
20
+ GRPC::ResourceExhausted => Error::LimitExceededError,
21
+ GRPC::Unauthenticated => Error::AuthenticationError,
22
+ GRPC::Unavailable => Error::ServerUnavailableError,
23
+ GRPC::Unimplemented => Error::BadRequestError,
24
+ GRPC::Unknown => Error::UnknownServiceError,
25
+ Momento::CacheNameError => Error::InvalidArgumentError
26
+ }.freeze
27
+
28
+ class << self
29
+ def from_exception(exception, context: {})
30
+ error_class = EXCEPTION_MAP[exception.class] || Error::UnknownError
31
+
32
+ error = error_class.new
33
+ error.context = context
34
+ error.cause = exception
35
+
36
+ case exception
37
+ when GRPC::BadStatus
38
+ error.transport_details = Error::TransportDetails.new(grpc: exception)
39
+ error.details = exception.details
40
+ else
41
+ error.details = exception.message
42
+ end
43
+
44
+ error.freeze
45
+
46
+ return error
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ module Momento
2
+ # Used to indicate an error in the cache name to be rescued
3
+ # and turned into an InvalidArgument respponse.
4
+ # @private
5
+ class CacheNameError < ::ArgumentError
6
+ end
7
+ end