startback-websocket 0.14.0 → 0.14.1
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 +4 -4
- data/Gemfile +3 -2
- data/README.md +64 -9
- data/lib/startback/ext/context.rb +6 -0
- data/lib/startback/ext.rb +1 -2
- data/lib/startback/websocket/app.rb +82 -0
- data/lib/startback/websocket/hub/app.rb +28 -0
- data/lib/startback/websocket/hub/builder.rb +55 -0
- data/lib/startback/websocket/hub/errors.rb +9 -0
- data/lib/startback/websocket/hub/message.rb +29 -0
- data/lib/startback/websocket/hub/middleware/command_handler.rb +34 -0
- data/lib/startback/websocket/hub/middleware/room_handler.rb +30 -0
- data/lib/startback/websocket/hub/middleware.rb +12 -0
- data/lib/startback/websocket/hub/participant.rb +16 -0
- data/lib/startback/websocket/hub/room.rb +46 -0
- data/lib/startback/websocket/hub.rb +15 -0
- data/lib/startback/websocket.rb +8 -0
- data/spec/spec_helper.rb +21 -32
- data/spec/unit/hub/test_builder.rb +141 -0
- data/spec/unit/hub/test_room.rb +27 -0
- data/spec/unit/test_app.rb +35 -0
- data/tasks/test.rake +0 -1
- metadata +20 -91
- data/lib/startback/audit/prometheus.rb +0 -87
- data/lib/startback/audit/shared.rb +0 -17
- data/lib/startback/audit/trailer.rb +0 -129
- data/lib/startback/audit.rb +0 -3
- data/lib/startback/caching/entity_cache.rb +0 -157
- data/lib/startback/caching/no_store.rb +0 -28
- data/lib/startback/caching/store.rb +0 -34
- data/lib/startback/context/h_factory.rb +0 -43
- data/lib/startback/context/middleware.rb +0 -53
- data/lib/startback/context.rb +0 -122
- data/lib/startback/errors.rb +0 -197
- data/lib/startback/event/agent.rb +0 -84
- data/lib/startback/event/bus/bunny/async.rb +0 -162
- data/lib/startback/event/bus/bunny.rb +0 -1
- data/lib/startback/event/bus/memory/async.rb +0 -45
- data/lib/startback/event/bus/memory/sync.rb +0 -35
- data/lib/startback/event/bus/memory.rb +0 -2
- data/lib/startback/event/bus.rb +0 -100
- data/lib/startback/event/engine.rb +0 -94
- data/lib/startback/event/ext/context.rb +0 -5
- data/lib/startback/event/ext/operation.rb +0 -13
- data/lib/startback/event.rb +0 -47
- data/lib/startback/ext/date_time.rb +0 -9
- data/lib/startback/ext/time.rb +0 -9
- data/lib/startback/model.rb +0 -6
- data/lib/startback/operation/error_operation.rb +0 -19
- data/lib/startback/operation/multi_operation.rb +0 -28
- data/lib/startback/operation.rb +0 -78
- data/lib/startback/services.rb +0 -11
- data/lib/startback/support/data_object.rb +0 -71
- data/lib/startback/support/env.rb +0 -41
- data/lib/startback/support/fake_logger.rb +0 -18
- data/lib/startback/support/hooks.rb +0 -48
- data/lib/startback/support/log_formatter.rb +0 -34
- data/lib/startback/support/logger.rb +0 -34
- data/lib/startback/support/operation_runner.rb +0 -150
- data/lib/startback/support/robustness.rb +0 -157
- data/lib/startback/support/transaction_manager.rb +0 -25
- data/lib/startback/support/transaction_policy.rb +0 -33
- data/lib/startback/support/world.rb +0 -54
- data/lib/startback/support.rb +0 -26
- data/lib/startback/version.rb +0 -8
- data/lib/startback/web/api.rb +0 -99
- data/lib/startback/web/auto_caching.rb +0 -85
- data/lib/startback/web/catch_all.rb +0 -52
- data/lib/startback/web/cors_headers.rb +0 -80
- data/lib/startback/web/health_check.rb +0 -49
- data/lib/startback/web/magic_assets/ng_html_transformer.rb +0 -80
- data/lib/startback/web/magic_assets/rake_tasks.rb +0 -64
- data/lib/startback/web/magic_assets.rb +0 -98
- data/lib/startback/web/middleware.rb +0 -13
- data/lib/startback/web/prometheus.rb +0 -16
- data/lib/startback/web/shield.rb +0 -58
- data/lib/startback.rb +0 -43
- data/spec/unit/audit/test_prometheus.rb +0 -72
- data/spec/unit/audit/test_trailer.rb +0 -105
- data/spec/unit/caching/test_entity_cache.rb +0 -136
- data/spec/unit/context/test_abstraction_factory.rb +0 -64
- data/spec/unit/context/test_dup.rb +0 -42
- data/spec/unit/context/test_fork.rb +0 -37
- data/spec/unit/context/test_h_factory.rb +0 -31
- data/spec/unit/context/test_middleware.rb +0 -45
- data/spec/unit/context/test_with_world.rb +0 -20
- data/spec/unit/context/test_world.rb +0 -17
- data/spec/unit/event/bus/memory/test_async.rb +0 -43
- data/spec/unit/event/bus/memory/test_sync.rb +0 -43
- data/spec/unit/support/hooks/test_after_hook.rb +0 -54
- data/spec/unit/support/hooks/test_before_hook.rb +0 -54
- data/spec/unit/support/operation_runner/test_around_run.rb +0 -156
- data/spec/unit/support/operation_runner/test_before_after_call.rb +0 -48
- data/spec/unit/support/test_data_object.rb +0 -156
- data/spec/unit/support/test_env.rb +0 -75
- data/spec/unit/support/test_robusteness.rb +0 -229
- data/spec/unit/support/test_transaction_manager.rb +0 -64
- data/spec/unit/support/test_world.rb +0 -72
- data/spec/unit/test_event.rb +0 -62
- data/spec/unit/test_operation.rb +0 -55
- data/spec/unit/test_support.rb +0 -40
- data/spec/unit/web/fixtures/assets/app/hello.es6 +0 -4
- data/spec/unit/web/fixtures/assets/app/hello.html +0 -1
- data/spec/unit/web/fixtures/assets/index.es6 +0 -1
- data/spec/unit/web/test_api.rb +0 -82
- data/spec/unit/web/test_auto_caching.rb +0 -81
- data/spec/unit/web/test_catch_all.rb +0 -77
- data/spec/unit/web/test_cors_headers.rb +0 -88
- data/spec/unit/web/test_healthcheck.rb +0 -59
- data/spec/unit/web/test_magic_assets.rb +0 -82
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Caching
|
|
3
|
-
#
|
|
4
|
-
# A overriable caching abstraction aiming at making Entity-based caching easy.
|
|
5
|
-
#
|
|
6
|
-
# This class MUST be overriden:
|
|
7
|
-
#
|
|
8
|
-
# * the `load_entity` protected method MUST be implemented to load data from
|
|
9
|
-
# a primary & context unaware key.
|
|
10
|
-
#
|
|
11
|
-
# * the `primary_key` protected method MAY be implemented to convert candidate
|
|
12
|
-
# keys (received from ultimate callers) to primary keys. The method is also
|
|
13
|
-
# a good place to check and/or log the keys actually used by callers.
|
|
14
|
-
#
|
|
15
|
-
# * the `context_free_key` protected method MAY be overriden to provide
|
|
16
|
-
# domain unrelated caching keys from primary keys, e.g. by encoding the
|
|
17
|
-
# context into the caching key itself, if needed.
|
|
18
|
-
#
|
|
19
|
-
# * the `valid?` protected method MAY be overriden to check validity of data
|
|
20
|
-
# extracted from the cache and force a refresh even if found.
|
|
21
|
-
#
|
|
22
|
-
# An EntityCache takes an actual store at construction. The object must meet the
|
|
23
|
-
# specification writtern in Store. The 'cache' ruby gem can be used in practice.
|
|
24
|
-
#
|
|
25
|
-
# Cache hits, outdated and miss are logged in debug, info, and info severity.
|
|
26
|
-
# The `cache_hit`, `cache_outdated`, `cache_miss` protected methods MAY be
|
|
27
|
-
# overriden to change that behavior.
|
|
28
|
-
#
|
|
29
|
-
class EntityCache
|
|
30
|
-
include Support::Robustness
|
|
31
|
-
|
|
32
|
-
class << self
|
|
33
|
-
|
|
34
|
-
# Default time to live, in seconds
|
|
35
|
-
attr_writer :default_ttl
|
|
36
|
-
|
|
37
|
-
def default_ttl
|
|
38
|
-
@default_ttl || (superclass.respond_to?(:default_ttl, true) && superclass.default_ttl) || 3600
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
end # class DSL
|
|
42
|
-
|
|
43
|
-
def initialize(store, context = nil)
|
|
44
|
-
@store = store
|
|
45
|
-
@context = context
|
|
46
|
-
end
|
|
47
|
-
attr_reader :store, :context
|
|
48
|
-
|
|
49
|
-
# Returns the entity corresponding to a given key.
|
|
50
|
-
#
|
|
51
|
-
# If the entity is not in cache, loads it and puts it in cache using
|
|
52
|
-
# the caching options passed as second parameter.
|
|
53
|
-
def get(candidate_key, caching_options = default_caching_options)
|
|
54
|
-
pkey = primary_key(candidate_key)
|
|
55
|
-
cache_key = encode_key(context_free_key(pkey))
|
|
56
|
-
if store.exist?(cache_key)
|
|
57
|
-
cached = store.get(cache_key)
|
|
58
|
-
if valid?(pkey, cached)
|
|
59
|
-
cache_hit(pkey, cached)
|
|
60
|
-
return cached
|
|
61
|
-
else
|
|
62
|
-
cache_outdated(pkey, cached)
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
cache_miss(pkey)
|
|
66
|
-
load_entity(pkey).tap{|to_cache|
|
|
67
|
-
store.set(cache_key, to_cache, caching_options)
|
|
68
|
-
}
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
# Invalidates the cache under a given key.
|
|
72
|
-
def invalidate(candidate_key)
|
|
73
|
-
pkey = primary_key(candidate_key)
|
|
74
|
-
cache_key = encode_key(context_free_key(pkey))
|
|
75
|
-
store.delete(cache_key)
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
protected
|
|
79
|
-
|
|
80
|
-
def cache_hit(pkey, cached)
|
|
81
|
-
log(:debug, self, "cache_hit", context, op_data: pkey)
|
|
82
|
-
end
|
|
83
|
-
|
|
84
|
-
def cache_outdated(pkey, cached)
|
|
85
|
-
log(:info, self, "cache_outdated", context, op_data: pkey)
|
|
86
|
-
end
|
|
87
|
-
|
|
88
|
-
def cache_miss(pkey)
|
|
89
|
-
log(:info, self, "cache_miss", context, op_data: pkey)
|
|
90
|
-
end
|
|
91
|
-
|
|
92
|
-
def default_caching_options
|
|
93
|
-
{ ttl: self.class.default_ttl }
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# Converts a candidate key to a primary key, so as to prevent
|
|
97
|
-
# cache duplicates if callers are allowed to request an entity
|
|
98
|
-
# through various keys.
|
|
99
|
-
#
|
|
100
|
-
# The default implementation returns the candidate key and MAY
|
|
101
|
-
# be overriden.
|
|
102
|
-
def primary_key(candidate_key)
|
|
103
|
-
candidate_key
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
# Encodes a context free key to an actual cache key.
|
|
107
|
-
#
|
|
108
|
-
# Default implementation uses JSON.fast_generate but MAY be
|
|
109
|
-
# overriden.
|
|
110
|
-
def encode_key(context_free_key)
|
|
111
|
-
JSON.fast_generate(context_free_key)
|
|
112
|
-
end
|
|
113
|
-
|
|
114
|
-
# Returns whether `cached` entity seems fresh enough to
|
|
115
|
-
# be returned as a cache hit.
|
|
116
|
-
#
|
|
117
|
-
# This method provides a way to check freshness using, e.g.
|
|
118
|
-
# `updated_at` or `etag` kind of entity fields. The default
|
|
119
|
-
# implementation returns true and MAY be overriden.
|
|
120
|
-
def valid?(primary_key, cached)
|
|
121
|
-
true
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# Converts a primary_key to a context_free_key, using the
|
|
125
|
-
# context (instance variable) to encode the context itself
|
|
126
|
-
# into the actual cache key.
|
|
127
|
-
#
|
|
128
|
-
# The default implementation simply returns the primary key
|
|
129
|
-
# and MAY be overriden.
|
|
130
|
-
def context_free_key(primary_key)
|
|
131
|
-
full_key(primary_key)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
|
-
# Deprecated, will be removed in 0.6.0. Use context_free_key
|
|
135
|
-
# instead.
|
|
136
|
-
def full_key(primary_key)
|
|
137
|
-
primary_key
|
|
138
|
-
end
|
|
139
|
-
|
|
140
|
-
# Actually loads the entity using the given primary key, and
|
|
141
|
-
# possibly the cache context.
|
|
142
|
-
#
|
|
143
|
-
# This method MUST be implemented and raises a NotImplementedError
|
|
144
|
-
# by default.
|
|
145
|
-
def load_entity(primary_key)
|
|
146
|
-
load_raw_data(primary_key)
|
|
147
|
-
end
|
|
148
|
-
|
|
149
|
-
# Deprecated, will be removed in 0.6.0. Use load_entity
|
|
150
|
-
# instead.
|
|
151
|
-
def load_raw_data(*args, &bl)
|
|
152
|
-
raise NotImplementedError, "#{self.class.name}#load_entity"
|
|
153
|
-
end
|
|
154
|
-
|
|
155
|
-
end # class EntityCache
|
|
156
|
-
end # module Caching
|
|
157
|
-
end # module Startback
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Caching
|
|
3
|
-
#
|
|
4
|
-
# Caching store implementation that caches nothing at all.
|
|
5
|
-
#
|
|
6
|
-
class NoStore
|
|
7
|
-
|
|
8
|
-
def initialize
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def exist?(key)
|
|
12
|
-
false
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def get(key)
|
|
16
|
-
nil
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def set(key, value, ttl)
|
|
20
|
-
value
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def delete(key)
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
end # class NoStore
|
|
27
|
-
end # module Caching
|
|
28
|
-
end # module Startback
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Caching
|
|
3
|
-
#
|
|
4
|
-
# Caching store specification & dummy implementation.
|
|
5
|
-
#
|
|
6
|
-
# This class should not be used in real project, as it implements
|
|
7
|
-
# See the 'cache' gem that provides conforming implementations.
|
|
8
|
-
#
|
|
9
|
-
class Store
|
|
10
|
-
|
|
11
|
-
def initialize
|
|
12
|
-
@saved = {}
|
|
13
|
-
end
|
|
14
|
-
attr_reader :saved
|
|
15
|
-
|
|
16
|
-
def exist?(key)
|
|
17
|
-
saved.has_key?(key)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def get(key)
|
|
21
|
-
saved[key]
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
def set(key, value, ttl)
|
|
25
|
-
saved[key] = value
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def delete(key)
|
|
29
|
-
saved.delete(key)
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
end # class Store
|
|
33
|
-
end # module Caching
|
|
34
|
-
end # module Startback
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
class Context
|
|
3
|
-
module HFactory
|
|
4
|
-
|
|
5
|
-
def h(hash)
|
|
6
|
-
h_factor!(self.new, hash)
|
|
7
|
-
end
|
|
8
|
-
|
|
9
|
-
def h_factor!(context, hash)
|
|
10
|
-
h_factories.each do |f|
|
|
11
|
-
f.call(context, hash)
|
|
12
|
-
end
|
|
13
|
-
context
|
|
14
|
-
end
|
|
15
|
-
|
|
16
|
-
def h_factories
|
|
17
|
-
@h_factories ||= []
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def h_factory(&factory)
|
|
21
|
-
h_factories << factory
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
###
|
|
25
|
-
|
|
26
|
-
def h_dump!(context, hash = {})
|
|
27
|
-
h_dumpers.each do |d|
|
|
28
|
-
context.instance_exec(hash, &d)
|
|
29
|
-
end
|
|
30
|
-
hash
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def h_dumpers
|
|
34
|
-
@h_dumpers ||= []
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def h_dump(&dumper)
|
|
38
|
-
h_dumpers << dumper
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
end # module HFactory
|
|
42
|
-
end # class Context
|
|
43
|
-
end # module Startback
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
class Context
|
|
3
|
-
#
|
|
4
|
-
# Rack middleware that installs a particular context instance
|
|
5
|
-
# on the Rack environment.
|
|
6
|
-
#
|
|
7
|
-
# Examples:
|
|
8
|
-
#
|
|
9
|
-
# # Use the default context class
|
|
10
|
-
# Rack::Builder.new do
|
|
11
|
-
# use Startback::Context::Middleware
|
|
12
|
-
#
|
|
13
|
-
# run ->(env){
|
|
14
|
-
# ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
|
|
15
|
-
# ctx.is_a?(Startback::Context) # => true
|
|
16
|
-
# }
|
|
17
|
-
# end
|
|
18
|
-
#
|
|
19
|
-
# # Use a user defined context class
|
|
20
|
-
# Rack::Builder.new do
|
|
21
|
-
# use Startback::Context::Middleware, MyContextClass.new
|
|
22
|
-
#
|
|
23
|
-
# run ->(env){
|
|
24
|
-
# ctx = env[Startback::Context::Middleware::RACK_ENV_KEY]
|
|
25
|
-
# ctx.is_a?(MyContextClass) # => true (your subclass)
|
|
26
|
-
# ctx.is_a?(Startback::Context) # => true (required!)
|
|
27
|
-
# }
|
|
28
|
-
# end
|
|
29
|
-
#
|
|
30
|
-
class Middleware
|
|
31
|
-
|
|
32
|
-
RACK_ENV_KEY = 'SAMBACK_CONTEXT'
|
|
33
|
-
|
|
34
|
-
def initialize(app, context = Context.new)
|
|
35
|
-
@app = app
|
|
36
|
-
@context = context
|
|
37
|
-
end
|
|
38
|
-
attr_reader :context
|
|
39
|
-
|
|
40
|
-
def call(env)
|
|
41
|
-
env[RACK_ENV_KEY] ||= context.dup.tap{|c|
|
|
42
|
-
c.original_rack_env = env.dup
|
|
43
|
-
}
|
|
44
|
-
@app.call(env)
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def self.context(env)
|
|
48
|
-
env[RACK_ENV_KEY]
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
end # class Middleware
|
|
52
|
-
end # class Context
|
|
53
|
-
end # module Startback
|
data/lib/startback/context.rb
DELETED
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
#
|
|
3
|
-
# Defines an execution context for Startback applications, and provides
|
|
4
|
-
# a cached factory for related abstractions (see `factor`), and an
|
|
5
|
-
# extensible world, statically and dynamically.
|
|
6
|
-
#
|
|
7
|
-
# In web application, an instance of a context can be set on the Rack
|
|
8
|
-
# environment, using Context::Middleware.
|
|
9
|
-
#
|
|
10
|
-
# This class SHOULD be subclassed for application required extensions
|
|
11
|
-
# to prevent touching the global Startback state itself.
|
|
12
|
-
#
|
|
13
|
-
# Also, for event handling in distributed architectures, a Context should
|
|
14
|
-
# be dumpable and reloadable to JSON. An `h` information contract if provided
|
|
15
|
-
# for that. Subclasses may contribute to the dumping and reloading process
|
|
16
|
-
# through the `h_dump` and `h_factory` methods
|
|
17
|
-
#
|
|
18
|
-
# module MyApp
|
|
19
|
-
# class Context < Startback::Context
|
|
20
|
-
#
|
|
21
|
-
# attr_accessor :foo
|
|
22
|
-
#
|
|
23
|
-
# h_dump do |h|
|
|
24
|
-
# h.merge!("foo" => foo)
|
|
25
|
-
# end
|
|
26
|
-
#
|
|
27
|
-
# h_factor do |c,h|
|
|
28
|
-
# c.foo = h["foo"]
|
|
29
|
-
# end
|
|
30
|
-
#
|
|
31
|
-
# end
|
|
32
|
-
# end
|
|
33
|
-
#
|
|
34
|
-
class Context
|
|
35
|
-
attr_accessor :original_rack_env
|
|
36
|
-
|
|
37
|
-
# An error handler can be provided on the Context class. The latter
|
|
38
|
-
# MUST expose an API similar to ruby's Logger class. It can be a logger
|
|
39
|
-
# instance, simply.
|
|
40
|
-
#
|
|
41
|
-
# Fatal errors catched by Web::CatchAll are sent on `error_handler#fatal`
|
|
42
|
-
#
|
|
43
|
-
# Deprecated, use the logger below instead.
|
|
44
|
-
attr_accessor :error_handler
|
|
45
|
-
|
|
46
|
-
# A logger can be provided on the context, and will be used for everything
|
|
47
|
-
# related to logging, audit trailing and robustness. The logger receives
|
|
48
|
-
# object following the log & trail conventions of Startback, and must
|
|
49
|
-
# convert them to wathever log format is necessary.
|
|
50
|
-
attr_accessor :logger
|
|
51
|
-
|
|
52
|
-
require_relative 'context/h_factory'
|
|
53
|
-
extend(Context::HFactory)
|
|
54
|
-
|
|
55
|
-
def initialize
|
|
56
|
-
super
|
|
57
|
-
yield(self) if block_given?
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
attr_writer :_world
|
|
61
|
-
protected :_world=
|
|
62
|
-
|
|
63
|
-
def self.world(who, &block)
|
|
64
|
-
@_world ||= Support::World.new
|
|
65
|
-
@_world = @_world.factory(who, &block)
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
def self.factor_world(context)
|
|
69
|
-
@_world ||= Support::World.new
|
|
70
|
-
@_world.with_scope(context)
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
def world
|
|
74
|
-
@_world ||= self.class.factor_world(self)
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
def with_world(world)
|
|
78
|
-
dup do |ctx|
|
|
79
|
-
ctx._world = self.world.with(world)
|
|
80
|
-
end
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
# Factors an instance of `clazz`, which must be a Context-related
|
|
84
|
-
# abstraction (i.e. its constructor takes the context as last parameters).
|
|
85
|
-
#
|
|
86
|
-
# Factored abstractions are cached for a given context & arguments.
|
|
87
|
-
def factor(clazz, *args)
|
|
88
|
-
@factored ||= {}
|
|
89
|
-
key = args.empty? ? clazz : [clazz] + args
|
|
90
|
-
@factored[key] ||= clazz.new(*(args << self))
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def clean_factored!
|
|
94
|
-
@factored = {}
|
|
95
|
-
end
|
|
96
|
-
private :clean_factored!
|
|
97
|
-
|
|
98
|
-
def to_h
|
|
99
|
-
self.class.h_dump!(self)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def to_json(*args, &bl)
|
|
103
|
-
to_h.to_json(*args, &bl)
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
def fork(h = nil)
|
|
107
|
-
dup.tap{|duped|
|
|
108
|
-
self.class.h_factor!(duped, h) if h
|
|
109
|
-
yield(duped) if block_given?
|
|
110
|
-
}
|
|
111
|
-
end
|
|
112
|
-
|
|
113
|
-
def dup
|
|
114
|
-
super.tap{|c|
|
|
115
|
-
c.send(:clean_factored!)
|
|
116
|
-
yield(c) if block_given?
|
|
117
|
-
}
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
end # class Context
|
|
121
|
-
end # module Startback
|
|
122
|
-
require_relative 'context/middleware'
|
data/lib/startback/errors.rb
DELETED
|
@@ -1,197 +0,0 @@
|
|
|
1
|
-
module Startback
|
|
2
|
-
module Errors
|
|
3
|
-
|
|
4
|
-
class Error < StandardError
|
|
5
|
-
def initialize(message = nil, causes = nil)
|
|
6
|
-
super(message)
|
|
7
|
-
@causes = Array(causes)
|
|
8
|
-
end
|
|
9
|
-
attr_reader :causes
|
|
10
|
-
|
|
11
|
-
class << self
|
|
12
|
-
def status(code = nil)
|
|
13
|
-
if code.nil?
|
|
14
|
-
@code || (superclass.respond_to?(:status) ? superclass.status : 500)
|
|
15
|
-
else
|
|
16
|
-
@code = code || @code
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
def keep_error(keep = nil)
|
|
21
|
-
@keep_error = keep unless keep.nil?
|
|
22
|
-
@keep_error
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
def message
|
|
27
|
-
msg = super
|
|
28
|
-
return msg unless msg == self.class.name
|
|
29
|
-
parts = self.class.name.split('::').last.gsub(/[A-Z]/){|x|
|
|
30
|
-
" #{x.downcase}"
|
|
31
|
-
}.strip.split(" ")
|
|
32
|
-
parts = parts[0...-1] unless self.class.keep_error
|
|
33
|
-
parts.join(" ").capitalize
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def has_causes?
|
|
37
|
-
causes && !causes.empty?
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def cause
|
|
41
|
-
causes&.first
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
class BadRequestError < Error
|
|
46
|
-
status 400
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
class UnauthorizedError < BadRequestError
|
|
50
|
-
status 401
|
|
51
|
-
end
|
|
52
|
-
|
|
53
|
-
class ForbiddenError < BadRequestError
|
|
54
|
-
status 403
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
class NotFoundError < BadRequestError
|
|
58
|
-
status 404
|
|
59
|
-
end
|
|
60
|
-
|
|
61
|
-
class MethodNotAllowedError < BadRequestError
|
|
62
|
-
status 405
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
class NotAcceptableError < BadRequestError
|
|
66
|
-
status 406
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
class ConflictError < BadRequestError
|
|
70
|
-
status 409
|
|
71
|
-
end
|
|
72
|
-
|
|
73
|
-
class GoneError < BadRequestError
|
|
74
|
-
status 410
|
|
75
|
-
end
|
|
76
|
-
|
|
77
|
-
class PreconditionFailedError < BadRequestError
|
|
78
|
-
status 412
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
class UnsupportedMediaTypeError < BadRequestError
|
|
82
|
-
status 415
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
class ExpectationFailedError < BadRequestError
|
|
86
|
-
status 417
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
class LockedError < BadRequestError
|
|
90
|
-
status 423
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
class PreconditionRequiredError < BadRequestError
|
|
94
|
-
status 428
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
class InternalServerError < Error
|
|
98
|
-
status 500
|
|
99
|
-
keep_error(true)
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
class NotImplementedError < InternalServerError
|
|
103
|
-
status 501
|
|
104
|
-
end
|
|
105
|
-
|
|
106
|
-
### Helper methods
|
|
107
|
-
|
|
108
|
-
def bad_request_error!(msg = nil)
|
|
109
|
-
raise Startback::Errors::BadRequestError, msg
|
|
110
|
-
end
|
|
111
|
-
module_function :bad_request_error!
|
|
112
|
-
|
|
113
|
-
def unauthorized_error!(msg = nil)
|
|
114
|
-
raise Startback::Errors::UnauthorizedError, msg
|
|
115
|
-
end
|
|
116
|
-
module_function :unauthorized_error!
|
|
117
|
-
|
|
118
|
-
def forbidden_error!(msg = nil)
|
|
119
|
-
raise Startback::Errors::ForbiddenError, msg
|
|
120
|
-
end
|
|
121
|
-
module_function :forbidden_error!
|
|
122
|
-
|
|
123
|
-
def not_found_error!(msg = nil)
|
|
124
|
-
raise Startback::Errors::NotFoundError, "#{msg} not found"
|
|
125
|
-
end
|
|
126
|
-
module_function :not_found_error!
|
|
127
|
-
|
|
128
|
-
def method_not_allowed_error!(msg = nil)
|
|
129
|
-
raise Startback::Errors::MethodNotAllowedError, msg
|
|
130
|
-
end
|
|
131
|
-
module_function :method_not_allowed_error!
|
|
132
|
-
|
|
133
|
-
def not_acceptable_error!(msg = nil)
|
|
134
|
-
raise Startback::Errors::NotAcceptableError, msg
|
|
135
|
-
end
|
|
136
|
-
module_function :not_acceptable_error!
|
|
137
|
-
|
|
138
|
-
def conflict_error!(msg = nil)
|
|
139
|
-
raise Startback::Errors::ConflictError, msg
|
|
140
|
-
end
|
|
141
|
-
module_function :conflict_error!
|
|
142
|
-
|
|
143
|
-
def gone_error!(msg = nil)
|
|
144
|
-
raise Startback::Errors::GoneError, msg
|
|
145
|
-
end
|
|
146
|
-
module_function :gone_error!
|
|
147
|
-
|
|
148
|
-
def precondition_failed_error!(msg = nil)
|
|
149
|
-
raise Startback::Errors::PreconditionFailedError, msg
|
|
150
|
-
end
|
|
151
|
-
module_function :precondition_failed_error!
|
|
152
|
-
|
|
153
|
-
def unsupported_media_type_error!(media)
|
|
154
|
-
raise Startback::Errors::UnsupportedMediaTypeError, "Unable to use `#{media}` as input data"
|
|
155
|
-
end
|
|
156
|
-
module_function :unsupported_media_type_error!
|
|
157
|
-
|
|
158
|
-
def expectation_failed_error!(msg = nil)
|
|
159
|
-
raise Startback::Errors::ExpectationFailedError, msg
|
|
160
|
-
end
|
|
161
|
-
module_function :expectation_failed_error!
|
|
162
|
-
|
|
163
|
-
def locked_error!(msg = nil)
|
|
164
|
-
raise Startback::Errors::LockedError, msg
|
|
165
|
-
end
|
|
166
|
-
module_function :locked_error!
|
|
167
|
-
|
|
168
|
-
def precondition_required_error!(msg = nil)
|
|
169
|
-
raise Startback::Errors::PreconditionRequiredError, msg
|
|
170
|
-
end
|
|
171
|
-
module_function :precondition_required_error!
|
|
172
|
-
|
|
173
|
-
def internal_server_error!(msg = nil)
|
|
174
|
-
raise Startback::Errors::InternalServerError, msg
|
|
175
|
-
end
|
|
176
|
-
module_function :internal_server_error!
|
|
177
|
-
|
|
178
|
-
def not_implemented_error!(msg = nil)
|
|
179
|
-
raise Startback::Errors::NotImplementedError, msg
|
|
180
|
-
end
|
|
181
|
-
module_function :not_implemented_error!
|
|
182
|
-
|
|
183
|
-
# Aliases
|
|
184
|
-
|
|
185
|
-
def user_error!(msg = nil)
|
|
186
|
-
raise Startback::Errors::BadRequestError, msg
|
|
187
|
-
end
|
|
188
|
-
module_function :user_error!
|
|
189
|
-
|
|
190
|
-
def server_error!(msg = nil)
|
|
191
|
-
raise Startback::Errors::InternalServerError, msg
|
|
192
|
-
end
|
|
193
|
-
module_function :server_error!
|
|
194
|
-
|
|
195
|
-
end # module Errors
|
|
196
|
-
include Errors
|
|
197
|
-
end # module Startback
|