momento 0.1.0 → 0.2.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 (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