falcon 0.55.6 → 0.56.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9efae16cb2a08be54e0b1099559fdb943d7ef5a85d709b57f4caa2590d08ff8f
4
- data.tar.gz: 4f03dd493732da1714b55ec9af8df3d1ec7e20ce0bd51e9ef48f5cee1e8141ed
3
+ metadata.gz: f7ba95aa9804ab5bccd97bdceb14467fc706c01bff4486e0ef8acac74a448567
4
+ data.tar.gz: b4a31ed06efddadc88a68de6d959a8b34310ec278edff5640b1b6149ce1bded3
5
5
  SHA512:
6
- metadata.gz: c0301ea50dea981115c09258abe18b55e8327bfcf2a74d018a4b1b7a55c1567521f8afb38b16b52a4559dc181df922af0408901bd7b79c6ac61a6cbc16b6c8b7
7
- data.tar.gz: 5270c593232e8d23d4157faa6b85176b5c95d220c4c0360871cb11e8990d04d1c2f508ef1681b1ff1e7c87fc408f5a68783d4fcf094812317ec8f241627d5a32
6
+ metadata.gz: 6ba9534e23c464859a54b955989c436fc1d0f639c17e621308098183fd477906db9a1348a52bb14b46ed02f16115913ee376da1e7886f782ce71ebb6869c538f
7
+ data.tar.gz: 4b3e498ac46f78a1f83d6fdcc2876dd91bc1ca8878f0c081579326f1fd757651d8baf02463a3038086a50f69a937e2d5cc84915c543a769ee74cddebeff99927
checksums.yaml.gz.sig CHANGED
Binary file
@@ -0,0 +1,197 @@
1
+ # Dynamic Clusters with Envoy
2
+
3
+ This guide explains how to run Falcon workers with independently bound endpoints and publish them dynamically to Envoy using xDS.
4
+
5
+ ## When to Use a Cluster
6
+
7
+ A regular {ruby Falcon::Service::Server} binds one listener and shares it with every worker. This is the simplest design when Falcon accepts connections directly or sits behind a load balancer that targets one stable address.
8
+
9
+ {ruby Falcon::Service::Cluster} instead gives each worker its own listener. Use it when an external load balancer needs to address, monitor, and remove workers individually. Because workers may bind ephemeral ports or Unix-domain sockets, the load balancer needs a dynamic source of viable endpoints rather than a static address list.
10
+
11
+ | Service | Listener ownership | Upstream discovery |
12
+ | --- | --- | --- |
13
+ | `Falcon::Service::Server` | One listener shared by all workers | One stable address |
14
+ | `Falcon::Service::Cluster` | One listener per worker | Dynamic worker endpoints |
15
+
16
+ ## Architecture
17
+
18
+ Each cluster worker can bind to `localhost` with port `0`, allowing the operating system to assign an available port. Falcon describes the bound resource with a {ruby Falcon::Listener}, including its name, scheme, supported protocols, and concrete addresses.
19
+
20
+ The worker registers that listener with `async-service-supervisor-envoy`. The supervisor publishes the current workers through an xDS control plane, and Envoy uses Endpoint Discovery Service (EDS) updates to maintain the upstream cluster.
21
+
22
+ Requests arrive at Envoy's stable listener. Envoy selects one of the discovered worker endpoints and forwards the request to it:
23
+
24
+ ```mermaid
25
+ flowchart LR
26
+ Client[Client] -->|HTTP on port 10000| Envoy
27
+
28
+ subgraph Network[Shared network namespace]
29
+ Envoy[Envoy]
30
+
31
+ subgraph Falcon[Falcon container]
32
+ Supervisor[Supervisor and xDS control plane]
33
+ Worker1[Falcon worker 1]
34
+ Worker2[Falcon worker 2]
35
+ end
36
+
37
+ Worker1 -.->|Register endpoint| Supervisor
38
+ Worker2 -.->|Register endpoint| Supervisor
39
+ Supervisor -.->|EDS over ADS on port 18000| Envoy
40
+ Envoy -->|HTTP on dynamic port| Worker1
41
+ Envoy -->|HTTP on dynamic port| Worker2
42
+ end
43
+ ```
44
+
45
+ ## Configuration
46
+
47
+ Add Falcon and the Envoy supervisor integration to your `gems.rb`:
48
+
49
+ ```ruby
50
+ gem "falcon", "~> 0.56.0"
51
+ gem "async-service-supervisor-envoy", "~> 0.2"
52
+ ```
53
+
54
+ Define a Falcon cluster service and an accompanying supervisor in `falcon.rb`:
55
+
56
+ ```ruby
57
+ #!/usr/bin/env async-service
58
+ # frozen_string_literal: true
59
+
60
+ require "async/service/supervisor"
61
+ require "async/service/supervisor/envoy"
62
+ require "falcon/environment/cluster"
63
+
64
+ service "cluster" do
65
+ include Falcon::Environment::Cluster
66
+ include Async::Service::Supervisor::Envoy::Supervised
67
+
68
+ count 2
69
+
70
+ def url
71
+ "http://localhost:0"
72
+ end
73
+
74
+ middleware do
75
+ application = proc do |_env|
76
+ body = "Hello from worker #{Process.pid}!\n"
77
+
78
+ [200, {
79
+ "content-type" => "text/plain",
80
+ "content-length" => body.bytesize.to_s,
81
+ }, [body]]
82
+ end
83
+
84
+ Falcon::Server.middleware(application, cache: false)
85
+ end
86
+ end
87
+
88
+ service "supervisor" do
89
+ include Async::Service::Supervisor::Environment
90
+
91
+ monitors do
92
+ [
93
+ Async::Service::Supervisor::Envoy::Monitor.new(
94
+ bind: "http://127.0.0.1:18000",
95
+ ),
96
+ ]
97
+ end
98
+ end
99
+ ```
100
+
101
+ The Falcon service name becomes the listener name, so the corresponding Envoy EDS cluster uses `cluster` as its service name. Configure Envoy to receive aggregated discovery updates from the supervisor:
102
+
103
+ ```yaml
104
+ node:
105
+ id: falcon-cluster
106
+ cluster: falcon-cluster
107
+
108
+ dynamic_resources:
109
+ ads_config:
110
+ api_type: GRPC
111
+ transport_api_version: V3
112
+ grpc_services:
113
+ - envoy_grpc:
114
+ cluster_name: xds_cluster
115
+
116
+ static_resources:
117
+ listeners:
118
+ - name: listener_http
119
+ address:
120
+ socket_address:
121
+ address: 0.0.0.0
122
+ port_value: 10000
123
+ filter_chains:
124
+ - filters:
125
+ - name: envoy.filters.network.http_connection_manager
126
+ typed_config:
127
+ "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
128
+ stat_prefix: ingress_http
129
+ route_config:
130
+ name: local_route
131
+ virtual_hosts:
132
+ - name: falcon
133
+ domains: ["*"]
134
+ routes:
135
+ - match:
136
+ prefix: "/"
137
+ route:
138
+ cluster: cluster
139
+ http_filters:
140
+ - name: envoy.filters.http.router
141
+ typed_config:
142
+ "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
143
+
144
+ clusters:
145
+ - name: cluster
146
+ connect_timeout: 1s
147
+ type: EDS
148
+ lb_policy: ROUND_ROBIN
149
+ eds_cluster_config:
150
+ service_name: cluster
151
+ eds_config:
152
+ ads: {}
153
+ resource_api_version: V3
154
+
155
+ - name: xds_cluster
156
+ connect_timeout: 1s
157
+ type: STATIC
158
+ load_assignment:
159
+ cluster_name: xds_cluster
160
+ endpoints:
161
+ - lb_endpoints:
162
+ - endpoint:
163
+ address:
164
+ socket_address:
165
+ address: 127.0.0.1
166
+ port_value: 18000
167
+ typed_extension_protocol_options:
168
+ envoy.extensions.upstreams.http.v3.HttpProtocolOptions:
169
+ "@type": type.googleapis.com/envoy.extensions.upstreams.http.v3.HttpProtocolOptions
170
+ explicit_http_config:
171
+ http2_protocol_options: {}
172
+ ```
173
+
174
+ The `xds_cluster` connection uses HTTP/2 because ADS is served over gRPC.
175
+
176
+ ## Worker Registration
177
+
178
+ When each worker starts:
179
+
180
+ 1. Falcon binds the worker to an available loopback port.
181
+ 2. The worker registers its concrete addresses and supported protocols with the supervisor.
182
+ 3. The supervisor's Envoy monitor publishes the current worker endpoints as an EDS resource.
183
+ 4. Envoy receives the resource over its Aggregated Discovery Service (ADS) connection and updates its upstream cluster.
184
+
185
+ The listener preserves all addresses returned by the bound endpoint. This allows the same interface to describe IP sockets, Unix-domain sockets, and endpoints with additional addresses.
186
+
187
+ ## Worker Restarts
188
+
189
+ If a worker exits, its supervisor connection closes and the monitor publishes an EDS update without that endpoint. Falcon restarts the worker, which binds a new available port and registers it. The monitor then publishes another update, and Envoy receives both changes over its existing ADS stream without polling or restarting.
190
+
191
+ This lifecycle is important when ports are ephemeral or a directory may contain stale Unix-domain socket paths: consumers should use the supervisor's current endpoint state as the source of truth.
192
+
193
+ ## Network Topology
194
+
195
+ Falcon and Envoy can run in the same network namespace, allowing workers to bind to loopback addresses while remaining reachable by Envoy. With Docker Compose, `network_mode: service:falcon` gives the Envoy service access to Falcon's network namespace, so `127.0.0.1` and `localhost` refer to the same loopback interface for both processes.
196
+
197
+ Without a shared network namespace, Envoy cannot connect to worker endpoints bound to Falcon's loopback interface. In a different deployment topology, bind workers to an interface that Envoy can reach and apply the appropriate network access controls.
data/context/index.yaml CHANGED
@@ -18,6 +18,10 @@ files:
18
18
  description: This guide explains how to deploy applications using the Falcon web
19
19
  server. It covers the recommended deployment methods, configuration options, and
20
20
  examples for different environments, including systemd and kubernetes.
21
+ - path: cluster-deployment.md
22
+ title: Dynamic Clusters with Envoy
23
+ description: This guide explains how to run Falcon workers with independently bound
24
+ endpoints and publish them dynamically to Envoy using xDS.
21
25
  - path: performance-tuning.md
22
26
  title: Performance Tuning
23
27
  description: This guide explains the performance characteristics of Falcon.
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require_relative "server"
7
+ require_relative "../service/cluster"
8
+
9
+ module Falcon
10
+ module Environment
11
+ # Provides an environment for hosting a cluster of Falcon server workers, where each worker binds its own endpoint.
12
+ module Cluster
13
+ include Server
14
+
15
+ # The service class to use for the cluster.
16
+ # @returns [Class]
17
+ def service_class
18
+ Service::Cluster
19
+ end
20
+
21
+ # The host that this server will receive connections for.
22
+ def url
23
+ "http://[::]:0"
24
+ end
25
+ end
26
+ end
27
+ end
@@ -67,6 +67,14 @@ module Falcon
67
67
  ::Async::HTTP::Endpoint.parse(url)
68
68
  end
69
69
 
70
+ # Prepare a server worker after its listener has been bound.
71
+ #
72
+ # @parameter instance [Object] The container instance.
73
+ # @parameter listener [Falcon::Listener] The worker's bound listener.
74
+ def prepare_worker!(instance, listener)
75
+ prepare!(instance)
76
+ end
77
+
70
78
  # Make a server instance using the given endpoint. The endpoint may be a bound endpoint, so we take care to specify the protocol and scheme as per the original endpoint.
71
79
  #
72
80
  # @parameter endpoint [IO::Endpoint] The endpoint to bind to.
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ module Falcon
7
+ # Describes a bound listener for a Falcon server.
8
+ class Listener
9
+ # Initialize a bound listener.
10
+ # @parameter name [String] The logical listener name.
11
+ # @parameter scheme [String] The application protocol scheme.
12
+ # @parameter protocols [Array(String)] The supported application protocol names.
13
+ # @parameter endpoint [IO::Endpoint::BoundEndpoint] The bound endpoint.
14
+ def initialize(name:, scheme:, protocols:, endpoint:)
15
+ @name = name
16
+ @scheme = scheme
17
+ @protocols = protocols.map(&:to_s).freeze
18
+ @endpoint = endpoint
19
+ @addresses = endpoint.sockets.map{|socket| socket.to_io.local_address}.freeze
20
+ freeze
21
+ end
22
+
23
+ # @attribute [String] The logical listener name.
24
+ attr_reader :name
25
+
26
+ # @attribute [String] The application protocol scheme.
27
+ attr_reader :scheme
28
+
29
+ # @attribute [Array(String)] The supported application protocol names.
30
+ attr_reader :protocols
31
+
32
+ # @attribute [IO::Endpoint::BoundEndpoint] The bound endpoint.
33
+ attr_reader :endpoint
34
+
35
+ # @attribute [Array(Addrinfo)] The bound addresses.
36
+ attr_reader :addresses
37
+
38
+ # Close the bound endpoint.
39
+ def close
40
+ @endpoint.close
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Released under the MIT License.
4
+ # Copyright, 2026, by Samuel Williams.
5
+
6
+ require_relative "server"
7
+
8
+ module Falcon
9
+ # @namespace
10
+ module Service
11
+ # A managed service for running Falcon workers with independently bound endpoints.
12
+ class Cluster < Server
13
+ # Cluster workers bind independently in their own process.
14
+ def bind_endpoint
15
+ end
16
+
17
+ # Bind and yield a listener owned by a cluster worker.
18
+ # @parameter evaluator [Environment::Evaluator] The environment evaluator.
19
+ # @yields {|listener| ...} The listener owned by the worker.
20
+ # @parameter listener [Falcon::Listener] The bound listener.
21
+ def with_listener(evaluator)
22
+ endpoint = evaluator.endpoint
23
+ bound_endpoint = endpoint.bound
24
+ listener = make_listener(evaluator, endpoint, bound_endpoint)
25
+
26
+ yield listener
27
+ ensure
28
+ bound_endpoint&.close
29
+ end
30
+ end
31
+ end
32
+ end
@@ -7,6 +7,7 @@
7
7
  require "async/service/managed/service"
8
8
  require "async/http/endpoint"
9
9
 
10
+ require_relative "../listener"
10
11
  require_relative "../server"
11
12
 
12
13
  module Falcon
@@ -18,35 +19,99 @@ module Falcon
18
19
  def initialize(...)
19
20
  super
20
21
 
21
- @bound_endpoint = nil
22
+ @listener = nil
22
23
  end
23
24
 
24
- # Prepare the bound endpoint for the server.
25
- def start
25
+ # Build a listener from a configured and bound endpoint.
26
+ # @parameter evaluator [Environment::Evaluator] The environment evaluator.
27
+ # @parameter endpoint [Async::HTTP::Endpoint] The configured endpoint.
28
+ # @parameter bound_endpoint [IO::Endpoint::BoundEndpoint] The bound endpoint.
29
+ # @returns [Falcon::Listener] The bound listener.
30
+ def make_listener(evaluator, endpoint, bound_endpoint)
31
+ Listener.new(
32
+ name: evaluator.name,
33
+ scheme: endpoint.scheme,
34
+ protocols: endpoint.protocol.names,
35
+ endpoint: bound_endpoint,
36
+ )
37
+ end
38
+
39
+ # Bind the endpoint used by each server worker.
40
+ def bind_endpoint
26
41
  @endpoint = @evaluator.endpoint
27
42
 
28
43
  Sync do
29
- @bound_endpoint = @endpoint.bound
44
+ bound_endpoint = @endpoint.bound
45
+ @listener = make_listener(@evaluator, @endpoint, bound_endpoint)
30
46
  end
31
47
 
32
48
  Console.info(self){"Starting #{self.name} on #{@endpoint}"}
49
+ end
50
+
51
+ # Prepare the bound endpoint for the server.
52
+ def start
53
+ bind_endpoint
33
54
 
34
55
  super
35
56
  end
36
57
 
58
+ # Yield the listener used by a server worker.
59
+ # @parameter evaluator [Environment::Evaluator] The environment evaluator.
60
+ # @yields {|listener| ...} The listener used by the worker.
61
+ # @parameter listener [Falcon::Listener] The bound listener.
62
+ def with_listener(evaluator)
63
+ yield @listener
64
+ end
65
+
66
+ # Setup the service into the specified container.
67
+ # @parameter container [Async::Container] The container to configure.
68
+ def setup(container)
69
+ container_options = @evaluator.container_options
70
+ health_check_timeout = container_options[:health_check_timeout]
71
+
72
+ container.run(**container_options) do |instance|
73
+ clock = Async::Clock.start
74
+ evaluator = self.environment.evaluator
75
+
76
+ with_listener(evaluator) do |listener|
77
+ Async do
78
+ server = nil
79
+
80
+ health_checker(instance, health_check_timeout) do
81
+ if server
82
+ instance.name = format_title(evaluator, server)
83
+ end
84
+ end
85
+
86
+ instance.status!("Preparing...")
87
+ evaluator.prepare_worker!(instance, listener)
88
+ emit_prepared(instance, clock)
89
+
90
+ instance.status!("Running...")
91
+ server = run(instance, evaluator, listener)
92
+ instance.name = format_title(evaluator, server)
93
+ emit_running(instance, clock)
94
+
95
+ instance.ready!
96
+ end
97
+ end
98
+ end
99
+ end
100
+
37
101
  # Run the service logic.
38
102
  #
39
103
  # @parameter instance [Object] The container instance.
40
104
  # @parameter evaluator [Environment::Evaluator] The environment evaluator.
105
+ # @parameter listener [Falcon::Listener] The listener used by this worker.
41
106
  # @returns [Falcon::Server] The server instance.
42
- def run(instance, evaluator)
107
+ def run(instance, evaluator, listener = @listener)
43
108
  if evaluator.respond_to?(:make_supervised_worker)
44
109
  Console.warn(self, "Async::Container::Supervisor is replaced by Async::Service::Supervisor, please update your service definition.")
45
110
 
46
111
  evaluator.make_supervised_worker(instance).run
47
112
  end
48
113
 
49
- server = evaluator.make_server(@bound_endpoint)
114
+ server = evaluator.make_server(listener.endpoint)
50
115
 
51
116
  Async do |task|
52
117
  server.run
@@ -69,9 +134,9 @@ module Falcon
69
134
 
70
135
  # Close the bound endpoint.
71
136
  def stop(...)
72
- if @bound_endpoint
73
- @bound_endpoint.close
74
- @bound_endpoint = nil
137
+ if @listener
138
+ @listener.close
139
+ @listener = nil
75
140
  end
76
141
 
77
142
  @endpoint = nil
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2020-2024, by Samuel Williams.
4
+ # Copyright, 2020-2026, by Samuel Williams.
5
5
 
6
6
  require "async/service/generic"
7
7
  require "console"
@@ -5,5 +5,5 @@
5
5
 
6
6
  # @namespace
7
7
  module Falcon
8
- VERSION = "0.55.6"
8
+ VERSION = "0.56.0"
9
9
  end
data/lib/falcon.rb CHANGED
@@ -4,6 +4,7 @@
4
4
  # Copyright, 2017-2026, by Samuel Williams.
5
5
 
6
6
  require_relative "falcon/version"
7
+ require_relative "falcon/listener"
7
8
  require_relative "falcon/server"
8
9
  require_relative "falcon/composite_server"
9
10
 
data/readme.md CHANGED
@@ -35,6 +35,8 @@ Please see the [project documentation](https://socketry.github.io/falcon/) for m
35
35
 
36
36
  - [Deployment](https://socketry.github.io/falcon/guides/deployment/index) - This guide explains how to deploy applications using the Falcon web server. It covers the recommended deployment methods, configuration options, and examples for different environments, including systemd and kubernetes.
37
37
 
38
+ - [Dynamic Clusters with Envoy](https://socketry.github.io/falcon/guides/cluster-deployment/index) - This guide explains how to run Falcon workers with independently bound endpoints and publish them dynamically to Envoy using xDS.
39
+
38
40
  - [Performance Tuning](https://socketry.github.io/falcon/guides/performance-tuning/index) - This guide explains the performance characteristics of Falcon.
39
41
 
40
42
  - [WebSockets](https://socketry.github.io/falcon/guides/websockets/index) - This guide explains how to use WebSockets with Falcon.
@@ -47,6 +49,11 @@ Please see the [project documentation](https://socketry.github.io/falcon/) for m
47
49
 
48
50
  Please see the [project releases](https://socketry.github.io/falcon/releases/index) for all releases.
49
51
 
52
+ ### v0.56.0
53
+
54
+ - Add `Falcon::Environment::Cluster` and `Falcon::Service::Cluster` for running workers with independently bound endpoints.
55
+ - Add `Falcon::Listener` to describe bound listeners shared by regular server workers or owned by cluster workers.
56
+
50
57
  ### v0.55.6
51
58
 
52
59
  - Move Falcon middleware trace providers to `traces/provider/falcon/middleware`.
@@ -87,10 +94,6 @@ Please see the [project releases](https://socketry.github.io/falcon/releases/ind
87
94
 
88
95
  - Introduce `Falcon::CompositeServer` for hosting multiple server instances in a single worker.
89
96
 
90
- ### v0.52.4
91
-
92
- - Relax dependency on `async-container-supervisor` to allow `~> 0.6`.
93
-
94
97
  ## Contributing
95
98
 
96
99
  We welcome contributions to this project.
data/releases.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Releases
2
2
 
3
+ ## v0.56.0
4
+
5
+ - Add `Falcon::Environment::Cluster` and `Falcon::Service::Cluster` for running workers with independently bound endpoints.
6
+ - Add `Falcon::Listener` to describe bound listeners shared by regular server workers or owned by cluster workers.
7
+
3
8
  ## v0.55.6
4
9
 
5
10
  - Move Falcon middleware trace providers to `traces/provider/falcon/middleware`.
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: falcon
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.55.6
4
+ version: 0.56.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -101,14 +101,14 @@ dependencies:
101
101
  requirements:
102
102
  - - "~>"
103
103
  - !ruby/object:Gem::Version
104
- version: '0.75'
104
+ version: '0.97'
105
105
  type: :runtime
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
109
  - - "~>"
110
110
  - !ruby/object:Gem::Version
111
- version: '0.75'
111
+ version: '0.97'
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: async-http-cache
114
114
  requirement: !ruby/object:Gem::Requirement
@@ -243,6 +243,7 @@ extra_rdoc_files: []
243
243
  files:
244
244
  - bin/falcon
245
245
  - bin/falcon-host
246
+ - context/cluster-deployment.md
246
247
  - context/deployment.md
247
248
  - context/extended-features.md
248
249
  - context/getting-started.md
@@ -267,6 +268,7 @@ files:
267
268
  - lib/falcon/endpoint.rb
268
269
  - lib/falcon/environment.rb
269
270
  - lib/falcon/environment/application.rb
271
+ - lib/falcon/environment/cluster.rb
270
272
  - lib/falcon/environment/configured.rb
271
273
  - lib/falcon/environment/lets_encrypt_tls.rb
272
274
  - lib/falcon/environment/proxy.rb
@@ -277,6 +279,7 @@ files:
277
279
  - lib/falcon/environment/server.rb
278
280
  - lib/falcon/environment/tls.rb
279
281
  - lib/falcon/environment/virtual.rb
282
+ - lib/falcon/listener.rb
280
283
  - lib/falcon/middleware/proxy.rb
281
284
  - lib/falcon/middleware/redirect.rb
282
285
  - lib/falcon/middleware/verbose.rb
@@ -284,6 +287,7 @@ files:
284
287
  - lib/falcon/rackup/handler.rb
285
288
  - lib/falcon/railtie.rb
286
289
  - lib/falcon/server.rb
290
+ - lib/falcon/service/cluster.rb
287
291
  - lib/falcon/service/server.rb
288
292
  - lib/falcon/service/virtual.rb
289
293
  - lib/falcon/tls.rb
metadata.gz.sig CHANGED
Binary file