ratalada 2.0.1 → 2.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.
- checksums.yaml +4 -4
- data/lib/ratalada/falcon.rb +11 -5
- data/lib/ratalada/puma.rb +3 -1
- data/lib/ratalada/version.rb +1 -1
- data/lib/ratalada.rb +70 -19
- metadata +32 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 1803a4b3f845951ed01752e1423b0c37c943b07ca1364f4b9d43e3c0a3add365
|
|
4
|
+
data.tar.gz: 104cf13b9244ecc47c975e3ea2a021db2869797bc7754fd2e745e016311780cc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5705db0d6d6e6a5145f5af7882fdb3c1cbd1abca7f4ac27bcfce1ecf576ef58ce35129bab5f4e4bd27a436796c53bfb49c3b87aee7ed0126f5ac5990db74727c
|
|
7
|
+
data.tar.gz: e42d339d4e674109a13276972d6513dddf8c2ce90c6c5e6d75f50ead33c4a9dc4932e5f9ab64e33c63882970138f0dc0d5df010726ac763427e23259e6d2a617
|
data/lib/ratalada/falcon.rb
CHANGED
|
@@ -27,20 +27,26 @@ module Ratalada
|
|
|
27
27
|
middleware = ::Falcon::Server.rack_middleware(app, cache: cache)
|
|
28
28
|
|
|
29
29
|
environment = Async::Service::Environment.new(::Falcon::Environment::Server).with(
|
|
30
|
-
name:
|
|
31
|
-
url:
|
|
32
|
-
middleware:
|
|
30
|
+
name: "ratalada",
|
|
31
|
+
url: "http://#{host}:#{port}",
|
|
32
|
+
middleware: -> { middleware },
|
|
33
33
|
container_options: { count: count, restart: true },
|
|
34
34
|
# async-service >= 0.25 reads `root` in Managed::Service#preload!
|
|
35
35
|
# unconditionally (the default `preload` is `[]`, which is truthy),
|
|
36
36
|
# so an environment without one raises NoMethodError on boot.
|
|
37
|
-
root:
|
|
37
|
+
root: Dir.pwd,
|
|
38
38
|
)
|
|
39
39
|
|
|
40
40
|
configuration = Async::Service::Configuration.new
|
|
41
41
|
configuration.add(environment)
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
if count > 1
|
|
44
|
+
workers = " (#{count} workers)"
|
|
45
|
+
else
|
|
46
|
+
workers = ""
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
warn "ratalada: falcon listening on http://#{host}:#{port}#{workers}"
|
|
44
50
|
Async::Service::Controller.run(configuration, container_class: Async::Container.best_container_class)
|
|
45
51
|
rescue Interrupt
|
|
46
52
|
# clean shutdown
|
data/lib/ratalada/puma.rb
CHANGED
|
@@ -9,7 +9,9 @@ module Ratalada
|
|
|
9
9
|
module_function
|
|
10
10
|
|
|
11
11
|
def run(app, host:, port:, count: 1)
|
|
12
|
-
|
|
12
|
+
if count > 1
|
|
13
|
+
warn "ratalada: puma backend ignores count: (not yet implemented)"
|
|
14
|
+
end
|
|
13
15
|
server = ::Puma::Server.new(app)
|
|
14
16
|
server.add_tcp_listener(host, port)
|
|
15
17
|
warn "ratalada: puma listening on http://#{host}:#{port}"
|
data/lib/ratalada/version.rb
CHANGED
data/lib/ratalada.rb
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "rack"
|
|
4
|
+
require "dry-configurable"
|
|
3
5
|
require_relative "ratalada/version"
|
|
4
6
|
|
|
5
7
|
module Ratalada
|
|
@@ -7,6 +9,8 @@ module Ratalada
|
|
|
7
9
|
DEFAULT_PORT = Integer(ENV.fetch("PORT", "9292"))
|
|
8
10
|
DEFAULT_COUNT = Integer(ENV.fetch("COUNT", "1"))
|
|
9
11
|
|
|
12
|
+
extend Dry::Configurable
|
|
13
|
+
|
|
10
14
|
class Error < StandardError; end
|
|
11
15
|
|
|
12
16
|
class NoBackendError < Error
|
|
@@ -35,18 +39,22 @@ module Ratalada
|
|
|
35
39
|
end
|
|
36
40
|
end
|
|
37
41
|
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
# Rack::Request plus just enough sugar to pattern match on, so everything
|
|
43
|
+
# rack already parses — params, cookies, headers, host, ip, session — comes
|
|
44
|
+
# along for free.
|
|
45
|
+
class Request < ::Rack::Request
|
|
46
|
+
# #path is PATH_INFO, not rack's own #path (SCRIPT_NAME + PATH_INFO):
|
|
47
|
+
# mounted under a `map`, routing here should match the path within this
|
|
48
|
+
# app, not the one the outer app was reached by.
|
|
46
49
|
def verb = env["REQUEST_METHOD"]
|
|
47
50
|
def path = env["PATH_INFO"]
|
|
48
51
|
def query = env["QUERY_STRING"]
|
|
49
|
-
|
|
52
|
+
|
|
53
|
+
# Rack's own #body is the rack.input stream; this is the whole of it as a
|
|
54
|
+
# String, memoized because rack 3 input reads once and does not rewind.
|
|
55
|
+
# To stream instead, chunk through #read and never touch #body.
|
|
56
|
+
def body = @body ||= read
|
|
57
|
+
def read(...) = env["rack.input"].read(...)
|
|
50
58
|
|
|
51
59
|
# Enables `in ["GET", "/"]`
|
|
52
60
|
def deconstruct = [verb, path]
|
|
@@ -62,6 +70,20 @@ module Ratalada
|
|
|
62
70
|
# triplet. No match (nil, or a fall-through `case ... in`) means 404.
|
|
63
71
|
module Routes
|
|
64
72
|
def self.build(block)
|
|
73
|
+
# Rack::Utils' helpers (escape_html, parse_query, set_cookie_header,
|
|
74
|
+
# ...) are callable unqualified inside the block, with no include at the
|
|
75
|
+
# call site and without instance_exec'ing it — self and ivars in the
|
|
76
|
+
# block stay the caller's. The include goes on the singleton of the
|
|
77
|
+
# object the block was written in, so nothing else in the process sees
|
|
78
|
+
# it, and since Rack::Utils is module_function'd they arrive as private
|
|
79
|
+
# methods that a receiver's own escape/status_code still overrides.
|
|
80
|
+
# ArgumentError: a C-level proc, which has no binding (&:symbol, #curry).
|
|
81
|
+
# TypeError: a frozen receiver. Neither can take the include; skip it.
|
|
82
|
+
begin
|
|
83
|
+
block.binding.receiver.singleton_class.include(::Rack::Utils)
|
|
84
|
+
rescue ArgumentError, TypeError
|
|
85
|
+
nil
|
|
86
|
+
end
|
|
65
87
|
App.new(block)
|
|
66
88
|
end
|
|
67
89
|
|
|
@@ -72,10 +94,10 @@ module Ratalada
|
|
|
72
94
|
|
|
73
95
|
def call(env)
|
|
74
96
|
request = Request.new(env)
|
|
75
|
-
|
|
76
|
-
@router.call(request)
|
|
97
|
+
begin
|
|
98
|
+
handler = @router.call(request)
|
|
77
99
|
rescue NoMatchingPatternError
|
|
78
|
-
nil
|
|
100
|
+
handler = nil
|
|
79
101
|
end
|
|
80
102
|
respond(handler, request)
|
|
81
103
|
end
|
|
@@ -114,8 +136,11 @@ module Ratalada
|
|
|
114
136
|
# count runs that many worker processes accepting from a shared socket,
|
|
115
137
|
# like node's cluster module. Each worker has its own state — anything
|
|
116
138
|
# shared (sessions, caches) needs an external store or count: 1.
|
|
117
|
-
|
|
118
|
-
|
|
139
|
+
#
|
|
140
|
+
# host:, port: and count: are written through to Ratalada.config before
|
|
141
|
+
# boot, so Server.run(port: 3000) is shorthand for configuring first.
|
|
142
|
+
def run(**options, &block)
|
|
143
|
+
Stack.new.run(**options, &block)
|
|
119
144
|
end
|
|
120
145
|
|
|
121
146
|
# The chain Server.use returns. Collects middleware until run ends it.
|
|
@@ -129,11 +154,29 @@ module Ratalada
|
|
|
129
154
|
self
|
|
130
155
|
end
|
|
131
156
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
157
|
+
# Every option is a Ratalada.config setting name (host, port, count);
|
|
158
|
+
# each is applied to the config verbatim — coercion and rejection of
|
|
159
|
+
# unknown names are the settings' own. Skipped entirely when no
|
|
160
|
+
# options are given so a finalized config can still boot.
|
|
161
|
+
def run(**options, &block)
|
|
162
|
+
unless block
|
|
163
|
+
raise ArgumentError, "Server.run requires a block"
|
|
164
|
+
end
|
|
135
165
|
|
|
136
|
-
|
|
166
|
+
if options.any?
|
|
167
|
+
Ratalada.configure do |config|
|
|
168
|
+
options.each do |key, value|
|
|
169
|
+
config[key] = value
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
config = Ratalada.config
|
|
175
|
+
unless config.count.is_a?(Integer) && config.count.positive?
|
|
176
|
+
raise ArgumentError, "count must be a positive Integer"
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
Ratalada.backend.run(to_app(block), host: config.host, port: config.port, count: config.count)
|
|
137
180
|
end
|
|
138
181
|
|
|
139
182
|
# First `use` in the chain is the outermost, as in Rack::Builder.
|
|
@@ -147,4 +190,12 @@ module Ratalada
|
|
|
147
190
|
end
|
|
148
191
|
|
|
149
192
|
# The whole point is a zero-ceremony top-level DSL.
|
|
150
|
-
|
|
193
|
+
unless defined?(Server)
|
|
194
|
+
Server = Ratalada::Server
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
# Core settings. Contrib gems (ratalada-contrib et al.) register theirs the
|
|
198
|
+
# same way — Ratalada.setting at the bottom of their own file.
|
|
199
|
+
Ratalada.setting :host, default: Ratalada::DEFAULT_HOST
|
|
200
|
+
Ratalada.setting :port, default: Ratalada::DEFAULT_PORT, constructor: ->(value) { Integer(value) }
|
|
201
|
+
Ratalada.setting :count, default: Ratalada::DEFAULT_COUNT, constructor: ->(value) { Integer(value) }
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ratalada
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.0
|
|
4
|
+
version: 2.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Nathan K
|
|
@@ -10,19 +10,47 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-01 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: rack
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
16
|
- - "~>"
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '3.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - "~>"
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '3.0'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: dry-configurable
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - "~>"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '1.4'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.4'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rspec
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '3.13'
|
|
19
47
|
type: :development
|
|
20
48
|
prerelease: false
|
|
21
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
50
|
requirements:
|
|
23
51
|
- - "~>"
|
|
24
52
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '
|
|
53
|
+
version: '3.13'
|
|
26
54
|
- !ruby/object:Gem::Dependency
|
|
27
55
|
name: rake
|
|
28
56
|
requirement: !ruby/object:Gem::Requirement
|