hoodoo 1.0.2
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.
- checksums.yaml +7 -0
- data/bin/hoodoo +5 -0
- data/lib/hoodoo.rb +27 -0
- data/lib/hoodoo/active.rb +32 -0
- data/lib/hoodoo/active/active_model/uuid_validator.rb +45 -0
- data/lib/hoodoo/active/active_record/base.rb +81 -0
- data/lib/hoodoo/active/active_record/creator.rb +134 -0
- data/lib/hoodoo/active/active_record/dated.rb +343 -0
- data/lib/hoodoo/active/active_record/error_mapping.rb +351 -0
- data/lib/hoodoo/active/active_record/finder.rb +606 -0
- data/lib/hoodoo/active/active_record/search_helper.rb +189 -0
- data/lib/hoodoo/active/active_record/secure.rb +431 -0
- data/lib/hoodoo/active/active_record/support.rb +106 -0
- data/lib/hoodoo/active/active_record/translated.rb +87 -0
- data/lib/hoodoo/active/active_record/uuid.rb +80 -0
- data/lib/hoodoo/active/active_record/writer.rb +321 -0
- data/lib/hoodoo/client.rb +23 -0
- data/lib/hoodoo/client/augmented_array.rb +29 -0
- data/lib/hoodoo/client/augmented_base.rb +168 -0
- data/lib/hoodoo/client/augmented_hash.rb +23 -0
- data/lib/hoodoo/client/client.rb +354 -0
- data/lib/hoodoo/client/endpoint/endpoint.rb +427 -0
- data/lib/hoodoo/client/endpoint/endpoints/amqp.rb +180 -0
- data/lib/hoodoo/client/endpoint/endpoints/auto_session.rb +194 -0
- data/lib/hoodoo/client/endpoint/endpoints/http.rb +203 -0
- data/lib/hoodoo/client/endpoint/endpoints/http_based.rb +367 -0
- data/lib/hoodoo/client/endpoint/endpoints/not_found.rb +59 -0
- data/lib/hoodoo/client/headers.rb +269 -0
- data/lib/hoodoo/communicators.rb +23 -0
- data/lib/hoodoo/communicators/fast.rb +44 -0
- data/lib/hoodoo/communicators/pool.rb +601 -0
- data/lib/hoodoo/communicators/slow.rb +84 -0
- data/lib/hoodoo/data.rb +51 -0
- data/lib/hoodoo/data/resources/caller.rb +39 -0
- data/lib/hoodoo/data/resources/errors.rb +28 -0
- data/lib/hoodoo/data/resources/log.rb +31 -0
- data/lib/hoodoo/data/resources/session.rb +26 -0
- data/lib/hoodoo/data/types/error_primitive.rb +27 -0
- data/lib/hoodoo/data/types/permissions.rb +40 -0
- data/lib/hoodoo/data/types/permissions_defaults.rb +32 -0
- data/lib/hoodoo/data/types/permissions_full.rb +28 -0
- data/lib/hoodoo/data/types/permissions_resources.rb +31 -0
- data/lib/hoodoo/discovery.rb +20 -0
- data/lib/hoodoo/errors.rb +19 -0
- data/lib/hoodoo/errors/error_descriptions.rb +229 -0
- data/lib/hoodoo/errors/errors.rb +322 -0
- data/lib/hoodoo/generator.rb +139 -0
- data/lib/hoodoo/logger.rb +23 -0
- data/lib/hoodoo/logger/fast_writer.rb +27 -0
- data/lib/hoodoo/logger/flattener_mixin.rb +36 -0
- data/lib/hoodoo/logger/logger.rb +387 -0
- data/lib/hoodoo/logger/slow_writer.rb +49 -0
- data/lib/hoodoo/logger/writer_mixin.rb +52 -0
- data/lib/hoodoo/logger/writers/file_writer.rb +45 -0
- data/lib/hoodoo/logger/writers/log_entries_dot_com_writer.rb +64 -0
- data/lib/hoodoo/logger/writers/stream_writer.rb +43 -0
- data/lib/hoodoo/middleware.rb +33 -0
- data/lib/hoodoo/presenters.rb +45 -0
- data/lib/hoodoo/presenters/base.rb +281 -0
- data/lib/hoodoo/presenters/base_dsl.rb +519 -0
- data/lib/hoodoo/presenters/common_resource_fields.rb +31 -0
- data/lib/hoodoo/presenters/embedding.rb +232 -0
- data/lib/hoodoo/presenters/types/array.rb +118 -0
- data/lib/hoodoo/presenters/types/boolean.rb +26 -0
- data/lib/hoodoo/presenters/types/date.rb +26 -0
- data/lib/hoodoo/presenters/types/date_time.rb +26 -0
- data/lib/hoodoo/presenters/types/decimal.rb +47 -0
- data/lib/hoodoo/presenters/types/enum.rb +55 -0
- data/lib/hoodoo/presenters/types/field.rb +158 -0
- data/lib/hoodoo/presenters/types/float.rb +26 -0
- data/lib/hoodoo/presenters/types/hash.rb +361 -0
- data/lib/hoodoo/presenters/types/integer.rb +26 -0
- data/lib/hoodoo/presenters/types/object.rb +117 -0
- data/lib/hoodoo/presenters/types/string.rb +53 -0
- data/lib/hoodoo/presenters/types/tags.rb +24 -0
- data/lib/hoodoo/presenters/types/text.rb +26 -0
- data/lib/hoodoo/presenters/types/uuid.rb +54 -0
- data/lib/hoodoo/services.rb +34 -0
- data/lib/hoodoo/services/discovery/discoverers/by_consul.rb +66 -0
- data/lib/hoodoo/services/discovery/discoverers/by_convention.rb +173 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/by_drb.rb +195 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server.rb +166 -0
- data/lib/hoodoo/services/discovery/discoverers/by_drb/drb_server_start.rb +37 -0
- data/lib/hoodoo/services/discovery/discovery.rb +186 -0
- data/lib/hoodoo/services/discovery/results/for_amqp.rb +58 -0
- data/lib/hoodoo/services/discovery/results/for_http.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_local.rb +85 -0
- data/lib/hoodoo/services/discovery/results/for_remote.rb +57 -0
- data/lib/hoodoo/services/middleware/amqp_log_message.rb +186 -0
- data/lib/hoodoo/services/middleware/amqp_log_writer.rb +119 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_local.rb +130 -0
- data/lib/hoodoo/services/middleware/endpoints/inter_resource_remote.rb +202 -0
- data/lib/hoodoo/services/middleware/exception_reporting/base_reporter.rb +105 -0
- data/lib/hoodoo/services/middleware/exception_reporting/exception_reporting.rb +115 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/airbrake_reporter.rb +64 -0
- data/lib/hoodoo/services/middleware/exception_reporting/reporters/raygun_reporter.rb +63 -0
- data/lib/hoodoo/services/middleware/interaction.rb +127 -0
- data/lib/hoodoo/services/middleware/middleware.rb +2705 -0
- data/lib/hoodoo/services/middleware/rack_monkey_patch.rb +73 -0
- data/lib/hoodoo/services/services/context.rb +153 -0
- data/lib/hoodoo/services/services/implementation.rb +132 -0
- data/lib/hoodoo/services/services/interface.rb +934 -0
- data/lib/hoodoo/services/services/permissions.rb +250 -0
- data/lib/hoodoo/services/services/request.rb +189 -0
- data/lib/hoodoo/services/services/response.rb +316 -0
- data/lib/hoodoo/services/services/service.rb +141 -0
- data/lib/hoodoo/services/services/session.rb +729 -0
- data/lib/hoodoo/utilities.rb +12 -0
- data/lib/hoodoo/utilities/string_inquirer.rb +54 -0
- data/lib/hoodoo/utilities/utilities.rb +380 -0
- data/lib/hoodoo/utilities/uuid.rb +44 -0
- data/lib/hoodoo/version.rb +17 -0
- data/spec/active/active_record/base_spec.rb +57 -0
- data/spec/active/active_record/creator_spec.rb +88 -0
- data/spec/active/active_record/dated_spec.rb +248 -0
- data/spec/active/active_record/error_mapping_spec.rb +360 -0
- data/spec/active/active_record/finder_spec.rb +744 -0
- data/spec/active/active_record/search_helper_spec.rb +384 -0
- data/spec/active/active_record/secure_spec.rb +435 -0
- data/spec/active/active_record/support_spec.rb +225 -0
- data/spec/active/active_record/translated_spec.rb +19 -0
- data/spec/active/active_record/uuid_spec.rb +72 -0
- data/spec/active/active_record/writer_spec.rb +272 -0
- data/spec/alchemy/alchemy-amq.rb +33 -0
- data/spec/client/augmented_array_spec.rb +15 -0
- data/spec/client/augmented_base_spec.rb +50 -0
- data/spec/client/augmented_hash_spec.rb +15 -0
- data/spec/client/client_spec.rb +955 -0
- data/spec/client/endpoint/endpoint_spec.rb +70 -0
- data/spec/client/endpoint/endpoints/amqp_spec.rb +16 -0
- data/spec/client/endpoint/endpoints/auto_session_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_based_spec.rb +9 -0
- data/spec/client/endpoint/endpoints/http_spec.rb +103 -0
- data/spec/client/endpoint/endpoints/not_found_spec.rb +35 -0
- data/spec/client/headers_spec.rb +172 -0
- data/spec/communicators/fast_spec.rb +9 -0
- data/spec/communicators/pool_spec.rb +339 -0
- data/spec/communicators/slow_spec.rb +15 -0
- data/spec/data/resources/caller_spec.rb +156 -0
- data/spec/data/resources/errors_spec.rb +22 -0
- data/spec/data/resources/log_spec.rb +20 -0
- data/spec/data/resources/session_spec.rb +15 -0
- data/spec/data/types/error_primitive_spec.rb +15 -0
- data/spec/data/types/permissions_defaults_spec.rb +25 -0
- data/spec/data/types/permissions_full_spec.rb +44 -0
- data/spec/data/types/permissions_resources_spec.rb +34 -0
- data/spec/data/types/permissions_spec.rb +37 -0
- data/spec/errors/error_descriptions_spec.rb +98 -0
- data/spec/errors/errors_spec.rb +346 -0
- data/spec/integration/service_actions_spec.rb +112 -0
- data/spec/logger/fast_writer_spec.rb +18 -0
- data/spec/logger/logger_spec.rb +259 -0
- data/spec/logger/slow_writer_spec.rb +144 -0
- data/spec/logger/writers/file_writer_spec.rb +37 -0
- data/spec/logger/writers/log_entries_dot_com_writer_spec.rb +29 -0
- data/spec/logger/writers/stream_writer_spec.rb +38 -0
- data/spec/presenters/base_dsl_spec.rb +111 -0
- data/spec/presenters/base_spec.rb +871 -0
- data/spec/presenters/common_resource_fields_spec.rb +30 -0
- data/spec/presenters/embedding_spec.rb +87 -0
- data/spec/presenters/types/array_spec.rb +249 -0
- data/spec/presenters/types/boolean_spec.rb +51 -0
- data/spec/presenters/types/date_spec.rb +57 -0
- data/spec/presenters/types/date_time_spec.rb +59 -0
- data/spec/presenters/types/decimal_spec.rb +58 -0
- data/spec/presenters/types/enum_spec.rb +71 -0
- data/spec/presenters/types/field_spec.rb +77 -0
- data/spec/presenters/types/float_spec.rb +50 -0
- data/spec/presenters/types/hash_spec.rb +1069 -0
- data/spec/presenters/types/integer_spec.rb +50 -0
- data/spec/presenters/types/object_spec.rb +177 -0
- data/spec/presenters/types/string_spec.rb +65 -0
- data/spec/presenters/types/tags_spec.rb +56 -0
- data/spec/presenters/types/text_spec.rb +50 -0
- data/spec/presenters/types/uuid_spec.rb +46 -0
- data/spec/presenters/walk_spec.rb +198 -0
- data/spec/services/discovery/discoverers/by_consul_spec.rb +29 -0
- data/spec/services/discovery/discoverers/by_convention_spec.rb +67 -0
- data/spec/services/discovery/discoverers/by_drb/by_drb_spec.rb +80 -0
- data/spec/services/discovery/discoverers/by_drb/drb_server_spec.rb +205 -0
- data/spec/services/discovery/discovery_spec.rb +73 -0
- data/spec/services/discovery/results/for_amqp_spec.rb +17 -0
- data/spec/services/discovery/results/for_http_spec.rb +37 -0
- data/spec/services/discovery/results/for_local_spec.rb +21 -0
- data/spec/services/discovery/results/for_remote_spec.rb +15 -0
- data/spec/services/middleware/amqp_log_message_spec.rb +60 -0
- data/spec/services/middleware/amqp_log_writer_spec.rb +95 -0
- data/spec/services/middleware/endpoints/inter_resource_local_spec.rb +9 -0
- data/spec/services/middleware/endpoints/inter_resource_remote_spec.rb +9 -0
- data/spec/services/middleware/exception_reporting/base_reporter_spec.rb +16 -0
- data/spec/services/middleware/exception_reporting/exception_reporting_spec.rb +92 -0
- data/spec/services/middleware/exception_reporting/reporters/airbrake_reporter_spec.rb +24 -0
- data/spec/services/middleware/exception_reporting/reporters/raygun_reporter_spec.rb +23 -0
- data/spec/services/middleware/middleware_cors_spec.rb +93 -0
- data/spec/services/middleware/middleware_create_update_spec.rb +489 -0
- data/spec/services/middleware/middleware_dated_at_spec.rb +186 -0
- data/spec/services/middleware/middleware_exotic_communication_spec.rb +560 -0
- data/spec/services/middleware/middleware_logging_spec.rb +356 -0
- data/spec/services/middleware/middleware_multi_local_spec.rb +1094 -0
- data/spec/services/middleware/middleware_multi_remote_spec.rb +1440 -0
- data/spec/services/middleware/middleware_permissions_spec.rb +1014 -0
- data/spec/services/middleware/middleware_public_spec.rb +238 -0
- data/spec/services/middleware/middleware_spec.rb +1569 -0
- data/spec/services/middleware/string_inquirer_spec.rb +30 -0
- data/spec/services/services/application_spec.rb +74 -0
- data/spec/services/services/context_spec.rb +48 -0
- data/spec/services/services/implementation_spec.rb +45 -0
- data/spec/services/services/interface_spec.rb +262 -0
- data/spec/services/services/permissions_spec.rb +249 -0
- data/spec/services/services/request_spec.rb +95 -0
- data/spec/services/services/response_spec.rb +250 -0
- data/spec/services/services/session_spec.rb +432 -0
- data/spec/spec_helper.rb +298 -0
- data/spec/utilities/utilities_spec.rb +537 -0
- data/spec/utilities/uuid_spec.rb +20 -0
- metadata +615 -0
@@ -0,0 +1,427 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: endpoint.rb
|
3
|
+
# (C):: Loyalty New Zealand 2015
|
4
|
+
#
|
5
|
+
# Purpose:: Resource endpoint definition.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 05-Mar-2015 (ADH): Created.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
module Hoodoo
|
11
|
+
class Client # Just used as a namespace here
|
12
|
+
|
13
|
+
# Base class for endpoint code.
|
14
|
+
#
|
15
|
+
# This base class defines the API to which subclasses must adhere,
|
16
|
+
# so that endpoint users don't need to care how the endpoint
|
17
|
+
# actually communicates with a target resource.
|
18
|
+
#
|
19
|
+
# ENDPOINTS ARE NOT INTENDED TO BE THREAD SAFE. Whenever you want to
|
20
|
+
# use one from a particular thread, instantiate an endpoint for use by
|
21
|
+
# just that thread. Don't share instances between threads via e.g.
|
22
|
+
# controlling class instance variables recording a reference to a
|
23
|
+
# single endpoint object.
|
24
|
+
#
|
25
|
+
class Endpoint
|
26
|
+
|
27
|
+
# Endpoint factory - instantiates and endpoint for the given resource
|
28
|
+
# and implemented API version, using the given discoverer.
|
29
|
+
#
|
30
|
+
# +resource+:: Resource name the endpoint targets, e.g. +:Purchase+.
|
31
|
+
# String or symbol.
|
32
|
+
#
|
33
|
+
# +version+:: Optional required interface (API) version for that
|
34
|
+
# endpoint. Integer. Default is 1.
|
35
|
+
#
|
36
|
+
# +options+:: Options Hash. Options are described below. Note that
|
37
|
+
# this Hash may be modified during processing.
|
38
|
+
#
|
39
|
+
# Items in the options hash are required, unless explicitly listed
|
40
|
+
# as optional. They are:
|
41
|
+
#
|
42
|
+
# +discoverer+:: A Hoodoo::Services::Discovery "By..." family
|
43
|
+
# member instance, e.g. a
|
44
|
+
# Hoodoo::Services::Discovery::ByDRb instance.
|
45
|
+
# This is used to look up a service instance. The
|
46
|
+
# returned discovery data type is used to determine
|
47
|
+
# the required endpoint type; for example, a
|
48
|
+
# Hoodoo::Services::Discovery::ForHTTP result yields
|
49
|
+
# a Hoodoo::Client::Endpoint::HTTP instance.
|
50
|
+
#
|
51
|
+
# +session_id+:: A session UUID, for the X-Session-ID HTTP header
|
52
|
+
# or an equivalent. Optional, but if omitted, only
|
53
|
+
# public resource actions will be accessible.
|
54
|
+
#
|
55
|
+
# +interaction+:: Optional Hoodoo::Services::Middleware::Interaction
|
56
|
+
# instance which describes a *source* interaction at
|
57
|
+
# hand. This is a middleware concept and most of the
|
58
|
+
# time, only the middleware would use this; the
|
59
|
+
# middleware is handling some API call which the
|
60
|
+
# source interaction data describes but the resource
|
61
|
+
# which is handling the call needs to make an
|
62
|
+
# inter-resource call, which is why an Endpoint is
|
63
|
+
# being created.
|
64
|
+
#
|
65
|
+
# +locale+:: Locale string for request/response, e.g. "en-gb".
|
66
|
+
# Optional. If omitted, defaults to "en-nz".
|
67
|
+
#
|
68
|
+
# OTHERS:: See Hoodoo::Client::Headers' +HEADER_TO_PROPERTY+.
|
69
|
+
# All such option keys _MUST_ be Symbols.
|
70
|
+
#
|
71
|
+
# Returns a Hoodoo::Services::Discovery "For..." family member
|
72
|
+
# instance (e.g. Hoodoo::Services::Discovery::ForHTTP) which can be
|
73
|
+
# used to talk to the resource in question. Getting an instance does
|
74
|
+
# not mean the resource endpoint is found - you will not know that
|
75
|
+
# until you try to talk to it and get a 404 expressed as a platform
|
76
|
+
# error in the response data. See Hoodoo::Client::AugmentedHash and
|
77
|
+
# Hoodoo::Client::AugmentedArray.
|
78
|
+
#
|
79
|
+
# Callers dealing with inter-resource call code may want to consult
|
80
|
+
# their discoverer to see if the resource is locally available
|
81
|
+
# before bothering to instantiate an endpoint.
|
82
|
+
#
|
83
|
+
# If the +deja_vu+ option is set, then a confirmed case of deja vu
|
84
|
+
# results in an empty Hash being returned, with no platform errors
|
85
|
+
# associated. This is the high-level transport neutral equivalent of
|
86
|
+
# (say) a 204 HTTP response with no body.
|
87
|
+
#
|
88
|
+
def self.endpoint_for( resource, version, options )
|
89
|
+
discoverer = options.delete( :discoverer )
|
90
|
+
discovery_result = discoverer.discover( resource.to_sym, version.to_i )
|
91
|
+
|
92
|
+
klass = if discovery_result.is_a?( Hoodoo::Services::Discovery::ForHTTP )
|
93
|
+
Hoodoo::Client::Endpoint::HTTP
|
94
|
+
elsif discovery_result.is_a?( Hoodoo::Services::Discovery::ForAMQP )
|
95
|
+
Hoodoo::Client::Endpoint::AMQP
|
96
|
+
elsif discovery_result.nil?
|
97
|
+
Hoodoo::Client::Endpoint::NotFound
|
98
|
+
else
|
99
|
+
nil
|
100
|
+
end
|
101
|
+
|
102
|
+
options[ :discovery_result ] = discovery_result
|
103
|
+
|
104
|
+
if klass.nil?
|
105
|
+
raise "Hoodoo::Client::Endpoint::endpoint_for: Unrecognised discoverer result class of '#{ discovery_result.class.name }'"
|
106
|
+
else
|
107
|
+
return klass.new( resource, version, options )
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Define read/write accessors for properties related to "X-Foo"
|
112
|
+
# headers. See the Middleware for details.
|
113
|
+
#
|
114
|
+
Hoodoo::Client::Headers.define_accessors_for_header_equivalents( self )
|
115
|
+
|
116
|
+
# The resource name passed to the constructor, as a String.
|
117
|
+
#
|
118
|
+
attr_reader :resource
|
119
|
+
|
120
|
+
# The version number passed to the constructor, as an Integer.
|
121
|
+
#
|
122
|
+
attr_reader :version
|
123
|
+
|
124
|
+
# The value of the +interaction+ option key passed to the
|
125
|
+
# constructor. See the constructor and #endpoint_for for more.
|
126
|
+
#
|
127
|
+
attr_reader :interaction
|
128
|
+
|
129
|
+
# The session UUID passed to the constructor or some value provided
|
130
|
+
# later; used for the calls to the target resource via the X-Session-ID
|
131
|
+
# HTTP header or an equivalent. If +nil+, only public actions in the
|
132
|
+
# target resource will be accessible.
|
133
|
+
#
|
134
|
+
attr_accessor :session_id
|
135
|
+
|
136
|
+
# The locale passed to the constructor or some value provided later; a
|
137
|
+
# String, e.g. "en-gb", or if +nil+, uses "en-nz" by default.
|
138
|
+
#
|
139
|
+
attr_accessor :locale
|
140
|
+
|
141
|
+
# Create an endpoint instance that will be used to make requests to
|
142
|
+
# a given resource.
|
143
|
+
#
|
144
|
+
# +resource+:: Resource name the endpoint targets, e.g. +:Purchase+.
|
145
|
+
# String or symbol.
|
146
|
+
#
|
147
|
+
# +version+:: Optional required interface (API) version for that
|
148
|
+
# endpoint. Integer. Default is 1.
|
149
|
+
#
|
150
|
+
# +options+:: Options Hash. Options are described below. Note that
|
151
|
+
# this Hash may be modified during processing.
|
152
|
+
#
|
153
|
+
# Items in the options hash are required, unless explicitly listed
|
154
|
+
# as optional. They are:
|
155
|
+
#
|
156
|
+
# +discovery_result+:: A Hoodoo::Services::Discovery "For..." family
|
157
|
+
# member instance, e.g. a
|
158
|
+
# Hoodoo::Services::Discovery::ForHTTP instance.
|
159
|
+
# Each subclass describes its required discovery
|
160
|
+
# result type, so see its documentation for
|
161
|
+
# details.
|
162
|
+
#
|
163
|
+
# +interaction+:: As in the options for #endpoint_for.
|
164
|
+
#
|
165
|
+
# +session_id+:: As in the options for #endpoint_for.
|
166
|
+
#
|
167
|
+
# +locale+:: As in the options for #endpoint_for.
|
168
|
+
#
|
169
|
+
# OTHERS:: See Hoodoo::Client::Headers' +HEADER_TO_PROPERTY+.
|
170
|
+
# All such option keys _MUST_ be Symbols.
|
171
|
+
#
|
172
|
+
# The out-of-the box initialiser sets up the data for the #resource,
|
173
|
+
# #version, #discovery_result, #interaction, #session_id, #locale,
|
174
|
+
# #dated_at and #dated_from accessors using this data, so subclass
|
175
|
+
# authors don't need to.
|
176
|
+
#
|
177
|
+
# The endpoint is then used with #list, #show, #create, #update or
|
178
|
+
# #delete methods to perform operations on the target resource. See
|
179
|
+
# each of those methods for details of their specific requirements;
|
180
|
+
# however all have common parameters some or all of which are used
|
181
|
+
# across the method 'family':
|
182
|
+
#
|
183
|
+
# +ident+:: Identifier. This is usually a UUID but some Resources
|
184
|
+
# support e.g. a "show" action based on either a UUID
|
185
|
+
# or some other unique value (such as a product code,
|
186
|
+
# a credit/debit card number or so-on - defined by the
|
187
|
+
# Resource in question in its documentation).
|
188
|
+
#
|
189
|
+
# +query_hash+:: A hash of _unencoded_ data that can be encoded to form
|
190
|
+
# a query string. Search and filter data is represented
|
191
|
+
# with nested hashes. Embed and reference data uses an
|
192
|
+
# array. Example:
|
193
|
+
#
|
194
|
+
# {
|
195
|
+
# offset: 75,
|
196
|
+
# limit: 50,
|
197
|
+
# sort: 'created_at', # ...or an Array of sort fields
|
198
|
+
# direction: 'asc', # ...or a matching Array of directions
|
199
|
+
# search: {
|
200
|
+
# member_id: "...some UUID..."
|
201
|
+
# },
|
202
|
+
# _embed: [
|
203
|
+
# 'vouchers',
|
204
|
+
# 'balances'
|
205
|
+
# ],
|
206
|
+
# # and/or ...filter: {}..., _reference: []...
|
207
|
+
# }
|
208
|
+
#
|
209
|
+
# This parameter is always optional.
|
210
|
+
#
|
211
|
+
# +body_hash+:: The Hash representation of the body data that might be
|
212
|
+
# sent in an HTTP request (i.e. JSON, as a Hash).
|
213
|
+
#
|
214
|
+
def initialize( resource, version = 1, options )
|
215
|
+
@resource = resource.to_sym
|
216
|
+
@version = version.to_i
|
217
|
+
|
218
|
+
@discovery_result = options[ :discovery_result ]
|
219
|
+
@interaction = options[ :interaction ]
|
220
|
+
|
221
|
+
self.session_id = options[ :session_id ]
|
222
|
+
self.locale = options[ :locale ]
|
223
|
+
|
224
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
225
|
+
property = description[ :property ]
|
226
|
+
property_writer = description[ :property_writer ]
|
227
|
+
|
228
|
+
self.send( property_writer, options[ property ] ) if options.has_key?( property )
|
229
|
+
end
|
230
|
+
|
231
|
+
configure_with( @resource, @version, options )
|
232
|
+
end
|
233
|
+
|
234
|
+
########################################################################
|
235
|
+
# And then subclass authors implement...
|
236
|
+
########################################################################
|
237
|
+
|
238
|
+
protected
|
239
|
+
|
240
|
+
# This protected method is implemented by subclasses and called from
|
241
|
+
# the initializer. Subclasses should store resource and version data
|
242
|
+
# however they want and validate any required options, raising errors
|
243
|
+
# if need be.
|
244
|
+
#
|
245
|
+
# +resource+:: Resource name the endpoint targets, e.g. +:Purchase+.
|
246
|
+
# Symbol.
|
247
|
+
#
|
248
|
+
# +version+:: Optional required interface (API) version for that
|
249
|
+
# endpoint. Integer.
|
250
|
+
#
|
251
|
+
# +options+:: Options Hash. Same as for #initialize.
|
252
|
+
#
|
253
|
+
def configure_with( resource, version, options )
|
254
|
+
raise "Subclasses must implement Hoodoo::Client::Endpoint\#configure_with"
|
255
|
+
end
|
256
|
+
|
257
|
+
# Utility method to aid subclass authors. Not usually overridden.
|
258
|
+
#
|
259
|
+
# Determine the response class needed for a given action - returns
|
260
|
+
# Hoodoo::Client::AugmentedArray or Hoodoo::Client::AugmentedHash
|
261
|
+
# (class references, not instances).
|
262
|
+
#
|
263
|
+
# +action+:: A Symbol from
|
264
|
+
# Hoodoo::Services::Middleware::ALLOWED_ACTIONS.
|
265
|
+
#
|
266
|
+
def response_class_for( action )
|
267
|
+
return action === :list ? Hoodoo::Client::AugmentedArray : Hoodoo::Client::AugmentedHash
|
268
|
+
end
|
269
|
+
|
270
|
+
# Utility method to aid subclass authors. Not usually overridden.
|
271
|
+
#
|
272
|
+
# Return an instance of Hoodoo::Client::AugmentedArray or
|
273
|
+
# Hoodoo::Client::AugmentedHash with an associated 404 error (as
|
274
|
+
# a fully formed platform error) describing 'Not Found' for the
|
275
|
+
# target resource, version and given action.
|
276
|
+
#
|
277
|
+
# +action+:: A Symbol from
|
278
|
+
# Hoodoo::Services::Middleware::ALLOWED_ACTIONS.
|
279
|
+
#
|
280
|
+
def generate_404_response_for( action )
|
281
|
+
data = response_class_for( action ).new
|
282
|
+
data.platform_errors.add_error(
|
283
|
+
'platform.not_found',
|
284
|
+
'reference' => { :entity_name => "v#{ @version } of #{ @resource } interface endpoint" }
|
285
|
+
)
|
286
|
+
|
287
|
+
return data
|
288
|
+
end
|
289
|
+
|
290
|
+
# Copy the current value of writable options in this Endpoint
|
291
|
+
# instance, to another Endpoint instance. This is useful when one
|
292
|
+
# is wrapping another, but to the external user of the wrapping
|
293
|
+
# endpoint, they should just be able to set options in that item
|
294
|
+
# and have it act as if they'd set them on the thing which it is
|
295
|
+
# (not that the caller would know) wrapping.
|
296
|
+
#
|
297
|
+
# This includes copying over a +session_id+ field value, though
|
298
|
+
# often it'll subsequently be rewritten by the wrapping endpoint as
|
299
|
+
# it's wrapping something to provide special session management.
|
300
|
+
#
|
301
|
+
# WARNING: Any +nil+ internal state values will _not_ be copied.
|
302
|
+
#
|
303
|
+
def copy_updated_options_to( target_endpoint )
|
304
|
+
target_endpoint.session_id = self.session_id unless self.session_id.nil?
|
305
|
+
target_endpoint.locale = self.locale unless self.locale.nil?
|
306
|
+
|
307
|
+
Hoodoo::Client::Headers::HEADER_TO_PROPERTY.each do | rack_header, description |
|
308
|
+
property = description[ :property ]
|
309
|
+
property_writer = description[ :property_writer ]
|
310
|
+
|
311
|
+
value = self.send( property )
|
312
|
+
|
313
|
+
target_endpoint.send( property_writer, value ) unless value.nil?
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
public
|
318
|
+
|
319
|
+
# Obtain a list of resource instance representations.
|
320
|
+
#
|
321
|
+
# +query_hash+:: See the constructor for more. This is the only way
|
322
|
+
# to search or filter the list, via the target
|
323
|
+
# Resource's documented supported search/filter
|
324
|
+
# parameters and the platform's common all-Resources
|
325
|
+
# behaviour.
|
326
|
+
#
|
327
|
+
# Returns a Hoodoo::Client::AugmentedArray representation of the
|
328
|
+
# requested list of resource instances.
|
329
|
+
#
|
330
|
+
# Call Hoodoo::Client::AugmentedArray#platform_errors (or for
|
331
|
+
# service authors implementing resource endpoints, possibly call
|
332
|
+
# Hoodoo::Client::AugmentedArray#adds_errors_to? instead) on the
|
333
|
+
# returned instance to detect and resolve error conditions _before_
|
334
|
+
# examining its Array-derived contents.
|
335
|
+
#
|
336
|
+
# The array will be empty in successful responses if no items
|
337
|
+
# satisfying the list conditions were found. The array contents
|
338
|
+
# are undefined in the case of errors.
|
339
|
+
#
|
340
|
+
def list( query_hash = nil )
|
341
|
+
raise "Subclasses must implement Hoodoo::Client::Endpoint\#list"
|
342
|
+
end
|
343
|
+
|
344
|
+
# Obtain a resource instance representation.
|
345
|
+
#
|
346
|
+
# +ident+:: See the constructor for details.
|
347
|
+
# +query_hash+:: See the constructor for details.
|
348
|
+
#
|
349
|
+
# Returns a Hoodoo::Client::AugmentedHash representation of the
|
350
|
+
# requested resource instance.
|
351
|
+
#
|
352
|
+
# Call Hoodoo::Client::AugmentedHash#platform_errors (or for
|
353
|
+
# service authors implementing resource endpoints, possibly call
|
354
|
+
# Hoodoo::Client::AugmentedHash#adds_errors_to? instead)
|
355
|
+
# on the returned instance to detect and resolve error conditions
|
356
|
+
# _before_ examining its Hash-derived fields.
|
357
|
+
#
|
358
|
+
# The hash contents are undefined when errors are returned.
|
359
|
+
#
|
360
|
+
def show( ident, query_hash = nil )
|
361
|
+
raise "Subclasses must implement Hoodoo::Client::Endpoint\#show"
|
362
|
+
end
|
363
|
+
|
364
|
+
# Create a resource instance.
|
365
|
+
#
|
366
|
+
# +body_hash+:: See the constructor for details.
|
367
|
+
# +query_hash+:: See the constructor for details.
|
368
|
+
#
|
369
|
+
# Returns a Hoodoo::Client::AugmentedHash representation of the
|
370
|
+
# new resource instance.
|
371
|
+
#
|
372
|
+
# Call Hoodoo::Client::AugmentedHash#platform_errors (or for
|
373
|
+
# service authors implementing resource endpoints, possibly call
|
374
|
+
# Hoodoo::Client::AugmentedHash#adds_errors_to? instead)
|
375
|
+
# on the returned instance to detect and resolve error conditions
|
376
|
+
# _before_ examining its Hash-derived fields.
|
377
|
+
#
|
378
|
+
# The hash contents are undefined when errors are returned.
|
379
|
+
#
|
380
|
+
def create( body_hash, query_hash = nil )
|
381
|
+
raise "Subclasses must implement Hoodoo::Client::Endpoint\#create"
|
382
|
+
end
|
383
|
+
|
384
|
+
# Update a resource instance.
|
385
|
+
#
|
386
|
+
# +ident+:: See the constructor for details.
|
387
|
+
# +body_hash+:: See the constructor for details.
|
388
|
+
# +query_hash+:: See the constructor for details.
|
389
|
+
#
|
390
|
+
# Returns a Hoodoo::Client::AugmentedHash representation of the
|
391
|
+
# updated resource instance.
|
392
|
+
#
|
393
|
+
# Call Hoodoo::Client::AugmentedHash#platform_errors (or for
|
394
|
+
# service authors implementing resource endpoints, possibly call
|
395
|
+
# Hoodoo::Client::AugmentedHash#adds_errors_to? instead)
|
396
|
+
# on the returned instance to detect and resolve error conditions
|
397
|
+
# _before_ examining its Hash-derived fields.
|
398
|
+
#
|
399
|
+
# The hash contents are undefined when errors are returned.
|
400
|
+
#
|
401
|
+
def update( ident, body_hash, query_hash = nil )
|
402
|
+
raise "Subclasses must implement Hoodoo::Client::Endpoint\#update"
|
403
|
+
end
|
404
|
+
|
405
|
+
# Delete a resource instance.
|
406
|
+
#
|
407
|
+
# +ident+:: See the constructor for details.
|
408
|
+
# +query_hash+:: See the constructor for details.
|
409
|
+
#
|
410
|
+
# Returns a Hoodoo::Client::AugmentedHash representation of the
|
411
|
+
# now-deleted resource instance,from the instant before deletion.
|
412
|
+
#
|
413
|
+
# Call Hoodoo::Client::AugmentedHash#platform_errors (or for
|
414
|
+
# service authors implementing resource endpoints, possibly call
|
415
|
+
# Hoodoo::Client::AugmentedHash#adds_errors_to? instead)
|
416
|
+
# on the returned instance to detect and resolve error conditions
|
417
|
+
# _before_ examining its Hash-derived fields.
|
418
|
+
#
|
419
|
+
# The hash contents are undefined when errors are returned.
|
420
|
+
#
|
421
|
+
def delete( ident, query_hash = nil )
|
422
|
+
raise "Subclasses must implement Hoodoo::Client::Endpoint\#delete"
|
423
|
+
end
|
424
|
+
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
########################################################################
|
2
|
+
# File:: amqp.rb
|
3
|
+
# (C):: Loyalty New Zealand 2015
|
4
|
+
#
|
5
|
+
# Purpose:: Resource endpoint definition.
|
6
|
+
# ----------------------------------------------------------------------
|
7
|
+
# 05-Mar-2015 (ADH): Created.
|
8
|
+
########################################################################
|
9
|
+
|
10
|
+
module Hoodoo
|
11
|
+
class Client # Just used as a namespace here
|
12
|
+
class Endpoint # Just used as a namespace here
|
13
|
+
|
14
|
+
# Talk to a resource that is contacted over AMQP using HTTP emulation
|
15
|
+
# via the Alchemy and AMQ Endpoint gems.
|
16
|
+
#
|
17
|
+
# Calls cannot be made until #alchemy= has been called
|
18
|
+
# to set an Alchemy caller instance. The Alchemy +http_request+ method
|
19
|
+
# is called on this instance to perform the over-queue HTTP simulation.
|
20
|
+
#
|
21
|
+
# Configured with a Hoodoo::Services::Discovery::ForAMQP discovery
|
22
|
+
# result instance.
|
23
|
+
#
|
24
|
+
class AMQP < Hoodoo::Client::Endpoint::HTTPBased
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
# See Hoodoo::Client::Endpoint#configure_with.
|
29
|
+
#
|
30
|
+
# Requires a Hoodoo::Services::Discovery::ForAMQP instance in the
|
31
|
+
# +discovery_result+ field of the +options+ Hash.
|
32
|
+
#
|
33
|
+
def configure_with( resource, version, options )
|
34
|
+
unless @discovery_result.is_a?( Hoodoo::Services::Discovery::ForAMQP )
|
35
|
+
raise "Hoodoo::Client::Endpoint::AMQP must be configured with a Hoodoo::Services::Discovery::ForAMQP instance - got '#{ @discovery_result.class.name }'"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Host and port isn't relevant for Alchemy but *is* needed
|
39
|
+
# to keep Rack happy.
|
40
|
+
|
41
|
+
endpoint_uri = URI.parse( 'http://localhost:80' )
|
42
|
+
endpoint_uri.path = @discovery_result.equivalent_path
|
43
|
+
|
44
|
+
@description = Hoodoo::Client::Endpoint::HTTPBased::DescriptionOfRequest.new
|
45
|
+
@description.discovery_result = @discovery_result
|
46
|
+
@description.endpoint_uri = endpoint_uri
|
47
|
+
end
|
48
|
+
|
49
|
+
public
|
50
|
+
|
51
|
+
# Set/get the Alchemy caller instance. Its +http_request+ method is
|
52
|
+
# called to perform the over-queue HTTP simulation.
|
53
|
+
#
|
54
|
+
# Instances of the AMQP endpoint can be created, but cannot be
|
55
|
+
# used for resource calls - #list, #show, #create, #update and
|
56
|
+
# #delete _cannot_ be called - until an Alchemy instance has been
|
57
|
+
# specified. An exception will be raised if you try.
|
58
|
+
#
|
59
|
+
attr_accessor :alchemy
|
60
|
+
|
61
|
+
# See Hoodoo::Client::Endpoint#list.
|
62
|
+
#
|
63
|
+
def list( query_hash = nil )
|
64
|
+
d = @description.dup # This does NOT dup the objects to which @description points
|
65
|
+
d.action = :list
|
66
|
+
d.query_hash = query_hash
|
67
|
+
|
68
|
+
return do_amqp( d )
|
69
|
+
end
|
70
|
+
|
71
|
+
# See Hoodoo::Client::Endpoint#show.
|
72
|
+
#
|
73
|
+
def show( ident, query_hash = nil )
|
74
|
+
d = @description.dup
|
75
|
+
d.action = :show
|
76
|
+
d.ident = ident
|
77
|
+
d.query_hash = query_hash
|
78
|
+
|
79
|
+
return do_amqp( d )
|
80
|
+
end
|
81
|
+
|
82
|
+
# See Hoodoo::Client::Endpoint#create.
|
83
|
+
#
|
84
|
+
def create( body_hash, query_hash = nil )
|
85
|
+
d = @description.dup
|
86
|
+
d.action = :create
|
87
|
+
d.body_hash = body_hash
|
88
|
+
d.query_hash = query_hash
|
89
|
+
|
90
|
+
return do_amqp( d )
|
91
|
+
end
|
92
|
+
|
93
|
+
# See Hoodoo::Client::Endpoint#update.
|
94
|
+
#
|
95
|
+
def update( ident, body_hash, query_hash = nil )
|
96
|
+
d = @description.dup
|
97
|
+
d.action = :update
|
98
|
+
d.ident = ident
|
99
|
+
d.body_hash = body_hash
|
100
|
+
d.query_hash = query_hash
|
101
|
+
|
102
|
+
return do_amqp( d )
|
103
|
+
end
|
104
|
+
|
105
|
+
# See Hoodoo::Client::Endpoint#delete.
|
106
|
+
#
|
107
|
+
def delete( ident, query_hash = nil )
|
108
|
+
d = @description.dup
|
109
|
+
d.action = :delete
|
110
|
+
d.ident = ident
|
111
|
+
d.query_hash = query_hash
|
112
|
+
|
113
|
+
return do_amqp( d )
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
# Call Alchemy to make an HTTP simulated request over AMQP to a
|
119
|
+
# target resource and return the result as a
|
120
|
+
# Hoodoo::Client::AugmentedArray (for 'list' calls) or
|
121
|
+
# Hoodoo::Client::AugumentedHash (for all other calls) instance.
|
122
|
+
#
|
123
|
+
# +description_of_request+:: A Hoodoo::Client::Endpoint::HTTPBased::DescriptionOfRequest
|
124
|
+
# instance with all the request details
|
125
|
+
# set inside. The +discovery_data+ field
|
126
|
+
# must refer to a
|
127
|
+
# Hoodoo::Services::Discovery::ForAMQP
|
128
|
+
# instance (not re-checked internally).
|
129
|
+
#
|
130
|
+
def do_amqp( description_of_request )
|
131
|
+
|
132
|
+
if self.alchemy().nil?
|
133
|
+
raise 'Hoodoo::Client::Endpoint::AMQP cannot be used unless an Alchemy instance has been provided'
|
134
|
+
end
|
135
|
+
|
136
|
+
action = description_of_request.action
|
137
|
+
data = get_data_for_request( description_of_request )
|
138
|
+
|
139
|
+
# Host and port are just there to keep Rack happy at the
|
140
|
+
# receiving end of the over-AMQP synthesised HTTP request.
|
141
|
+
|
142
|
+
alchemy_options = {
|
143
|
+
:host => description_of_request.endpoint_uri.host,
|
144
|
+
:port => description_of_request.endpoint_uri.port,
|
145
|
+
:query => data.query_hash,
|
146
|
+
:body => data.body_string,
|
147
|
+
:headers => data.header_hash
|
148
|
+
}
|
149
|
+
|
150
|
+
unless self.session_id().nil? # Session comes from Endpoint superclass
|
151
|
+
alchemy_options[ :session_id ] = self.session_id()
|
152
|
+
end
|
153
|
+
|
154
|
+
http_method = {
|
155
|
+
:create => 'POST',
|
156
|
+
:update => 'PATCH',
|
157
|
+
:delete => 'DELETE'
|
158
|
+
}[ action ] || 'GET'
|
159
|
+
|
160
|
+
description_of_response = DescriptionOfResponse.new
|
161
|
+
description_of_response.action = action
|
162
|
+
|
163
|
+
amqp_response = self.alchemy().http_request(
|
164
|
+
description_of_request.discovery_result.queue_name,
|
165
|
+
http_method,
|
166
|
+
data.full_uri.path,
|
167
|
+
alchemy_options
|
168
|
+
)
|
169
|
+
|
170
|
+
description_of_response.http_status_code = amqp_response.status_code.to_i
|
171
|
+
description_of_response.http_headers = amqp_response.headers || {}
|
172
|
+
description_of_response.raw_body_data = amqp_response.body
|
173
|
+
|
174
|
+
return get_data_for_response( description_of_response )
|
175
|
+
end
|
176
|
+
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|