rage-rb 1.15.1 → 1.17.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/CHANGELOG.md +25 -0
- data/Gemfile +1 -0
- data/OVERVIEW.md +32 -2
- data/README.md +3 -2
- data/lib/rage/all.rb +1 -0
- data/lib/rage/cable/adapters/redis.rb +1 -1
- data/lib/rage/cable/cable.rb +7 -2
- data/lib/rage/cable/channel.rb +4 -4
- data/lib/rage/cable/{protocol → protocols}/actioncable_v1_json.rb +30 -62
- data/lib/rage/cable/protocols/base.rb +88 -0
- data/lib/rage/cable/protocols/raw_web_socket_json.rb +144 -0
- data/lib/rage/cli.rb +20 -0
- data/lib/rage/code_loader.rb +25 -14
- data/lib/rage/configuration.rb +187 -3
- data/lib/rage/controller/api.rb +5 -1
- data/lib/rage/deferred/backends/disk.rb +258 -0
- data/lib/rage/deferred/backends/nil.rb +16 -0
- data/lib/rage/deferred/deferred.rb +95 -0
- data/lib/rage/deferred/metadata.rb +43 -0
- data/lib/rage/deferred/proxy.rb +34 -0
- data/lib/rage/deferred/queue.rb +78 -0
- data/lib/rage/deferred/task.rb +96 -0
- data/lib/rage/fiber_scheduler.rb +1 -0
- data/lib/rage/hooks.rb +25 -0
- data/lib/rage/openapi/parsers/ext/alba.rb +23 -9
- data/lib/rage/request.rb +0 -1
- data/lib/rage/response.rb +39 -0
- data/lib/rage/router/constrainer.rb +0 -2
- data/lib/rage/router/node.rb +0 -2
- data/lib/rage/rspec.rb +1 -1
- data/lib/rage/setup.rb +3 -0
- data/lib/rage/templates/controller-template/controller.rb +2 -0
- data/lib/rage/version.rb +1 -1
- data/lib/rage-rb.rb +9 -0
- data/rage.gemspec +2 -2
- metadata +17 -6
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Rage::Deferred::Proxy
|
4
|
+
class Wrapper
|
5
|
+
include Rage::Deferred::Task
|
6
|
+
|
7
|
+
def perform(instance, method_name, *, **)
|
8
|
+
instance.public_send(method_name, *, **)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(instance, delay: nil, delay_until: nil)
|
13
|
+
@instance = instance
|
14
|
+
|
15
|
+
@delay = delay
|
16
|
+
@delay_until = delay_until
|
17
|
+
end
|
18
|
+
|
19
|
+
def method_missing(method_name, *, **)
|
20
|
+
if @instance.respond_to?(method_name)
|
21
|
+
self.class.define_method(method_name) do |*args, **kwargs|
|
22
|
+
Wrapper.enqueue(@instance, method_name, *args, delay: @delay, delay_until: @delay_until, **kwargs)
|
23
|
+
end
|
24
|
+
|
25
|
+
send(method_name, *, **)
|
26
|
+
else
|
27
|
+
@instance.public_send(method_name, *, **)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def respond_to_missing?(method_name, _)
|
32
|
+
@instance.respond_to?(method_name)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Rage::Deferred::Queue
|
4
|
+
attr_reader :backlog_size
|
5
|
+
|
6
|
+
def initialize(backend)
|
7
|
+
@backend = backend
|
8
|
+
@backlog_size = 0
|
9
|
+
@backpressure = Rage.config.deferred.backpressure
|
10
|
+
end
|
11
|
+
|
12
|
+
# Write the task to the storage and schedule it for execution.
|
13
|
+
def enqueue(task_metadata, delay: nil, delay_until: nil, task_id: nil)
|
14
|
+
apply_backpressure if @backpressure
|
15
|
+
|
16
|
+
publish_in, publish_at = if delay
|
17
|
+
delay_i = delay.to_i
|
18
|
+
[delay_i, Time.now.to_i + delay_i] if delay_i > 0
|
19
|
+
elsif delay_until
|
20
|
+
delay_until_i, current_time_i = delay_until.to_i, Time.now.to_i
|
21
|
+
[delay_until_i - current_time_i, delay_until_i] if delay_until_i > current_time_i
|
22
|
+
end
|
23
|
+
|
24
|
+
persisted_task_id = @backend.add(task_metadata, publish_at:, task_id:)
|
25
|
+
schedule(persisted_task_id, task_metadata, publish_in:)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Schedule the task for execution.
|
29
|
+
def schedule(task_id, task_metadata, publish_in: nil)
|
30
|
+
publish_in_ms = publish_in.to_i * 1_000 if publish_in && publish_in > 0
|
31
|
+
task = Rage::Deferred::Metadata.get_task(task_metadata)
|
32
|
+
@backlog_size += 1 unless publish_in_ms
|
33
|
+
|
34
|
+
Iodine.run_after(publish_in_ms) do
|
35
|
+
@backlog_size -= 1 unless publish_in_ms
|
36
|
+
|
37
|
+
unless Iodine.stopping?
|
38
|
+
Fiber.schedule do
|
39
|
+
Iodine.task_inc!
|
40
|
+
|
41
|
+
is_completed = task.new.__perform(task_metadata)
|
42
|
+
|
43
|
+
if is_completed
|
44
|
+
@backend.remove(task_id)
|
45
|
+
else
|
46
|
+
attempts = Rage::Deferred::Metadata.inc_attempts(task_metadata)
|
47
|
+
if task.__should_retry?(attempts)
|
48
|
+
enqueue(task_metadata, delay: task.__next_retry_in(attempts), task_id:)
|
49
|
+
else
|
50
|
+
@backend.remove(task_id)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
ensure
|
55
|
+
Iodine.task_dec!
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def apply_backpressure
|
64
|
+
if @backlog_size > @backpressure.high_water_mark && !Fiber[:rage_backpressure_applied]
|
65
|
+
Fiber[:rage_backpressure_applied] = true
|
66
|
+
|
67
|
+
i, target_backlog_size = 0, @backpressure.low_water_mark
|
68
|
+
while @backlog_size > target_backlog_size && i < @backpressure.timeout_iterations
|
69
|
+
sleep @backpressure.sleep_interval
|
70
|
+
i += 1
|
71
|
+
end
|
72
|
+
|
73
|
+
if i == @backpressure.timeout_iterations
|
74
|
+
raise Rage::Deferred::PushTimeout, "could not enqueue deferred task within #{@backpressure.timeout} seconds"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# `Rage::Deferred::Task` is a module that should be included in classes that represent tasks to be executed
|
5
|
+
# in the background by the `Rage::Deferred` queue. It ensures the tasks can be retried in case of a failure,
|
6
|
+
# with a maximum number of attempts and an exponential backoff strategy.
|
7
|
+
#
|
8
|
+
# To define a task, include the module and implement the `#perform` method:
|
9
|
+
#
|
10
|
+
# ```ruby
|
11
|
+
# class ProcessImage
|
12
|
+
# include Rage::Deferred::Task
|
13
|
+
#
|
14
|
+
# def perform(image_path:)
|
15
|
+
# # logic to process the image
|
16
|
+
# end
|
17
|
+
# end
|
18
|
+
# ```
|
19
|
+
#
|
20
|
+
# The task can be enqueued using the `enqueue` method:
|
21
|
+
#
|
22
|
+
# ```ruby
|
23
|
+
# ProcessImage.enqueue(image_path: 'path/to/image.jpg')
|
24
|
+
# ```
|
25
|
+
#
|
26
|
+
# The `delay` and `delay_until` options can be used to specify when the task should be executed.
|
27
|
+
#
|
28
|
+
# ```ruby
|
29
|
+
# ProcessImage.enqueue(image_path: 'path/to/image.jpg', delay: 10) # delays execution by 10 seconds
|
30
|
+
# ProcessImage.enqueue(image_path: 'path/to/image.jpg', delay_until: Time.now + 3600) # executes after 1 hour
|
31
|
+
# ```
|
32
|
+
#
|
33
|
+
module Rage::Deferred::Task
|
34
|
+
MAX_ATTEMPTS = 5
|
35
|
+
private_constant :MAX_ATTEMPTS
|
36
|
+
|
37
|
+
BACKOFF_INTERVAL = 5
|
38
|
+
private_constant :BACKOFF_INTERVAL
|
39
|
+
|
40
|
+
def perform
|
41
|
+
end
|
42
|
+
|
43
|
+
# @private
|
44
|
+
def __with_optional_log_tag(tag)
|
45
|
+
if tag
|
46
|
+
Rage.logger.tagged(tag) { yield }
|
47
|
+
else
|
48
|
+
yield
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# @private
|
53
|
+
def __perform(metadata)
|
54
|
+
args = Rage::Deferred::Metadata.get_args(metadata)
|
55
|
+
kwargs = Rage::Deferred::Metadata.get_kwargs(metadata)
|
56
|
+
attempts = Rage::Deferred::Metadata.get_attempts(metadata)
|
57
|
+
request_id = Rage::Deferred::Metadata.get_request_id(metadata)
|
58
|
+
|
59
|
+
context = { task: self.class.name }
|
60
|
+
context[:attempt] = attempts + 1 if attempts
|
61
|
+
|
62
|
+
Rage.logger.with_context(context) do
|
63
|
+
__with_optional_log_tag(request_id) do
|
64
|
+
perform(*args, **kwargs)
|
65
|
+
true
|
66
|
+
rescue Exception => e
|
67
|
+
Rage.logger.error("Deferred task failed with exception: #{e.class} (#{e.message}):\n#{e.backtrace.join("\n")}")
|
68
|
+
false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.included(klass)
|
74
|
+
klass.extend(ClassMethods)
|
75
|
+
end
|
76
|
+
|
77
|
+
module ClassMethods
|
78
|
+
def enqueue(*args, delay: nil, delay_until: nil, **kwargs)
|
79
|
+
Rage::Deferred.__queue.enqueue(
|
80
|
+
Rage::Deferred::Metadata.build(self, args, kwargs),
|
81
|
+
delay:,
|
82
|
+
delay_until:
|
83
|
+
)
|
84
|
+
end
|
85
|
+
|
86
|
+
# @private
|
87
|
+
def __should_retry?(attempts)
|
88
|
+
attempts < MAX_ATTEMPTS
|
89
|
+
end
|
90
|
+
|
91
|
+
# @private
|
92
|
+
def __next_retry_in(attempts)
|
93
|
+
rand(BACKOFF_INTERVAL * 2**attempts.to_i) + 1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
data/lib/rage/fiber_scheduler.rb
CHANGED
data/lib/rage/hooks.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Hooks
|
4
|
+
def hooks
|
5
|
+
@hooks ||= Hash.new { |h, k| h[k] = [] }
|
6
|
+
end
|
7
|
+
|
8
|
+
def push_hook(callback, hook_family)
|
9
|
+
hooks[hook_family] << callback if callback.is_a?(Proc)
|
10
|
+
end
|
11
|
+
|
12
|
+
def run_hooks_for!(hook_family, context = nil)
|
13
|
+
hooks[hook_family].each do |callback|
|
14
|
+
if context
|
15
|
+
context.instance_exec(&callback)
|
16
|
+
else
|
17
|
+
callback.call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
@hooks[hook_family] = []
|
22
|
+
|
23
|
+
true
|
24
|
+
end
|
25
|
+
end
|
@@ -20,7 +20,7 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
20
20
|
|
21
21
|
def __parse_nested(klass_str)
|
22
22
|
__parse(klass_str).tap { |visitor|
|
23
|
-
visitor.root_key = visitor.root_key_for_collection = visitor.key_transformer = nil
|
23
|
+
visitor.root_key = visitor.root_key_for_collection = visitor.root_key_proc = visitor.key_transformer = nil
|
24
24
|
}.build_schema
|
25
25
|
end
|
26
26
|
|
@@ -50,7 +50,7 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
50
50
|
end
|
51
51
|
|
52
52
|
class Visitor < Prism::Visitor
|
53
|
-
attr_accessor :schema, :root_key, :root_key_for_collection, :key_transformer, :collection_key, :meta
|
53
|
+
attr_accessor :schema, :root_key, :root_key_for_collection, :root_key_proc, :key_transformer, :collection_key, :meta
|
54
54
|
|
55
55
|
def initialize(parser, is_collection)
|
56
56
|
@parser = parser
|
@@ -64,6 +64,7 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
64
64
|
@self_name = nil
|
65
65
|
@root_key = nil
|
66
66
|
@root_key_for_collection = nil
|
67
|
+
@root_key_proc = nil
|
67
68
|
@key_transformer = nil
|
68
69
|
@collection_key = false
|
69
70
|
@meta = {}
|
@@ -74,7 +75,7 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
74
75
|
|
75
76
|
if node.name =~ /Resource$|Serializer$/ && node.superclass
|
76
77
|
visitor = @parser.__parse(node.superclass.name)
|
77
|
-
@root_key, @root_key_for_collection = visitor.root_key, visitor.root_key_for_collection
|
78
|
+
@root_key, @root_key_for_collection, @root_key_proc = visitor.root_key, visitor.root_key_for_collection, visitor.root_key_proc
|
78
79
|
@key_transformer, @collection_key, @meta = visitor.key_transformer, visitor.collection_key, visitor.meta
|
79
80
|
@schema.merge!(visitor.schema)
|
80
81
|
end
|
@@ -87,6 +88,13 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
87
88
|
|
88
89
|
result["properties"] = @schema if @schema.any?
|
89
90
|
|
91
|
+
if @root_key_proc
|
92
|
+
dynamic_root_key, dynamic_root_key_for_collection = @root_key_proc.call(@self_name)
|
93
|
+
|
94
|
+
@root_key = dynamic_root_key
|
95
|
+
@root_key_for_collection = dynamic_root_key_for_collection
|
96
|
+
end
|
97
|
+
|
90
98
|
if @is_collection
|
91
99
|
result = if @collection_key && @root_key_for_collection
|
92
100
|
{ "type" => "object", "properties" => { @root_key_for_collection => { "type" => "object", "additionalProperties" => result }, **@meta } }
|
@@ -109,6 +117,7 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
109
117
|
def visit_call_node(node)
|
110
118
|
case node.name
|
111
119
|
when :root_key
|
120
|
+
@root_key_proc = nil
|
112
121
|
context = with_context { visit(node.arguments) }
|
113
122
|
@root_key, @root_key_for_collection = context.symbols
|
114
123
|
|
@@ -135,12 +144,13 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
135
144
|
when :many, :has_many, :one, :has_one, :association
|
136
145
|
is_array = node.name == :many || node.name == :has_many
|
137
146
|
context = with_context { visit(node.arguments) }
|
138
|
-
|
147
|
+
association = context.symbols[0]
|
148
|
+
key = context.keywords["key"] || association
|
139
149
|
|
140
150
|
if node.block
|
141
151
|
with_inner_segment(key, is_array:) { visit(node.block) }
|
142
152
|
else
|
143
|
-
resource = context.keywords["resource"] || (::Alba.inflector && "#{::Alba.inflector.classify(
|
153
|
+
resource = context.keywords["resource"] || (::Alba.inflector && "#{::Alba.inflector.classify(association.to_s)}Resource")
|
144
154
|
is_valid_resource = @parser.namespace.const_get(resource) rescue false
|
145
155
|
|
146
156
|
@segment[key] = if is_array
|
@@ -159,10 +169,14 @@ class Rage::OpenAPI::Parsers::Ext::Alba
|
|
159
169
|
|
160
170
|
when :root_key!
|
161
171
|
if (inflector = ::Alba.inflector)
|
162
|
-
|
163
|
-
|
164
|
-
@
|
165
|
-
|
172
|
+
@root_key, @root_key_for_collection = nil
|
173
|
+
|
174
|
+
@root_key_proc = ->(resource_name) do
|
175
|
+
suffix = resource_name.end_with?("Resource") ? "Resource" : "Serializer"
|
176
|
+
name = inflector.demodulize(resource_name).delete_suffix(suffix)
|
177
|
+
|
178
|
+
inflector.underscore(name).yield_self { |key| [key, inflector.pluralize(key)] }
|
179
|
+
end
|
166
180
|
end
|
167
181
|
end
|
168
182
|
end
|
data/lib/rage/request.rb
CHANGED
data/lib/rage/response.rb
CHANGED
@@ -1,6 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "digest"
|
4
|
+
require "time"
|
5
|
+
|
3
6
|
class Rage::Response
|
7
|
+
ETAG_HEADER = "ETag"
|
8
|
+
LAST_MODIFIED_HEADER = "Last-Modified"
|
9
|
+
|
4
10
|
# @private
|
5
11
|
def initialize(headers, body)
|
6
12
|
@headers = headers
|
@@ -18,4 +24,37 @@ class Rage::Response
|
|
18
24
|
def headers
|
19
25
|
@headers
|
20
26
|
end
|
27
|
+
|
28
|
+
# Returns ETag response header or +nil+ if it's empty.
|
29
|
+
#
|
30
|
+
# @return [String, nil]
|
31
|
+
def etag
|
32
|
+
headers[Rage::Response::ETAG_HEADER]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Sets ETag header to the response. Additionally, it will hashify the value using +Digest::SHA1.hexdigest+. Pass +nil+ for resetting it.
|
36
|
+
# @note ETag will be always Weak since no strong validation is implemented.
|
37
|
+
# @note ArgumentError is raised if ETag value is neither +String+, nor +nil+
|
38
|
+
# @param etag [String, nil] The etag of the resource in the response.
|
39
|
+
def etag=(etag)
|
40
|
+
raise ArgumentError, "Expected `String` but `#{etag.class}` is received" unless etag.is_a?(String) || etag.nil?
|
41
|
+
|
42
|
+
headers[Rage::Response::ETAG_HEADER] = etag.nil? ? nil : %(W/"#{Digest::SHA1.hexdigest(etag)}")
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns Last-Modified response header or +nil+ if it's empty.
|
46
|
+
#
|
47
|
+
# @return [String, nil]
|
48
|
+
def last_modified
|
49
|
+
headers[Rage::Response::LAST_MODIFIED_HEADER]
|
50
|
+
end
|
51
|
+
|
52
|
+
# Sets Last-Modified header to the response by calling httpdate on the argument.
|
53
|
+
# @note ArgumentError is raised if +last_modified+ is not a +Time+ object instance
|
54
|
+
# @param last_modified [Time, nil] The last modified time of the resource in the response.
|
55
|
+
def last_modified=(last_modified)
|
56
|
+
raise ArgumentError, "Expected `Time` but `#{last_modified.class}` is received" unless last_modified.is_a?(Time) || last_modified.nil?
|
57
|
+
|
58
|
+
headers[Rage::Response::LAST_MODIFIED_HEADER] = last_modified&.httpdate
|
59
|
+
end
|
21
60
|
end
|
data/lib/rage/router/node.rb
CHANGED
data/lib/rage/rspec.rb
CHANGED
data/lib/rage/setup.rb
CHANGED
data/lib/rage/version.rb
CHANGED
data/lib/rage-rb.rb
CHANGED
@@ -22,6 +22,10 @@ module Rage
|
|
22
22
|
Rage::OpenAPI
|
23
23
|
end
|
24
24
|
|
25
|
+
def self.deferred
|
26
|
+
Rage::Deferred
|
27
|
+
end
|
28
|
+
|
25
29
|
def self.routes
|
26
30
|
Rage::Router::DSL.new(__router)
|
27
31
|
end
|
@@ -107,6 +111,10 @@ module Rage
|
|
107
111
|
end
|
108
112
|
end
|
109
113
|
|
114
|
+
class << self
|
115
|
+
alias_method :configuration, :config
|
116
|
+
end
|
117
|
+
|
110
118
|
module Router
|
111
119
|
module Strategies
|
112
120
|
end
|
@@ -126,6 +134,7 @@ module Rage
|
|
126
134
|
autoload :Session, "rage/session"
|
127
135
|
autoload :Cable, "rage/cable/cable"
|
128
136
|
autoload :OpenAPI, "rage/openapi/openapi"
|
137
|
+
autoload :Deferred, "rage/deferred/deferred"
|
129
138
|
end
|
130
139
|
|
131
140
|
module RageController
|
data/rage.gemspec
CHANGED
@@ -11,7 +11,7 @@ Gem::Specification.new do |spec|
|
|
11
11
|
spec.summary = "Fast web framework compatible with Rails."
|
12
12
|
spec.homepage = "https://github.com/rage-rb/rage"
|
13
13
|
spec.license = "MIT"
|
14
|
-
spec.required_ruby_version = ">= 3.
|
14
|
+
spec.required_ruby_version = ">= 3.2.0"
|
15
15
|
|
16
16
|
spec.metadata["homepage_uri"] = spec.homepage
|
17
17
|
spec.metadata["source_code_uri"] = "https://github.com/rage-rb/rage"
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
|
30
30
|
spec.add_dependency "thor", "~> 1.0"
|
31
31
|
spec.add_dependency "rack", "~> 2.0"
|
32
|
-
spec.add_dependency "rage-iodine", "~> 4.
|
32
|
+
spec.add_dependency "rage-iodine", "~> 4.3"
|
33
33
|
spec.add_dependency "zeitwerk", "~> 2.6"
|
34
34
|
spec.add_dependency "rack-test", "~> 2.1"
|
35
35
|
spec.add_dependency "rake", ">= 12.0"
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rage-rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.17.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Roman Samoilov
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-08-20 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: thor
|
@@ -43,14 +43,14 @@ dependencies:
|
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: '4.
|
46
|
+
version: '4.3'
|
47
47
|
type: :runtime
|
48
48
|
prerelease: false
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
50
50
|
requirements:
|
51
51
|
- - "~>"
|
52
52
|
- !ruby/object:Gem::Version
|
53
|
-
version: '4.
|
53
|
+
version: '4.3'
|
54
54
|
- !ruby/object:Gem::Dependency
|
55
55
|
name: zeitwerk
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
@@ -119,19 +119,29 @@ files:
|
|
119
119
|
- lib/rage/cable/cable.rb
|
120
120
|
- lib/rage/cable/channel.rb
|
121
121
|
- lib/rage/cable/connection.rb
|
122
|
-
- lib/rage/cable/
|
122
|
+
- lib/rage/cable/protocols/actioncable_v1_json.rb
|
123
|
+
- lib/rage/cable/protocols/base.rb
|
124
|
+
- lib/rage/cable/protocols/raw_web_socket_json.rb
|
123
125
|
- lib/rage/cable/router.rb
|
124
126
|
- lib/rage/cli.rb
|
125
127
|
- lib/rage/code_loader.rb
|
126
128
|
- lib/rage/configuration.rb
|
127
129
|
- lib/rage/controller/api.rb
|
128
130
|
- lib/rage/cookies.rb
|
131
|
+
- lib/rage/deferred/backends/disk.rb
|
132
|
+
- lib/rage/deferred/backends/nil.rb
|
133
|
+
- lib/rage/deferred/deferred.rb
|
134
|
+
- lib/rage/deferred/metadata.rb
|
135
|
+
- lib/rage/deferred/proxy.rb
|
136
|
+
- lib/rage/deferred/queue.rb
|
137
|
+
- lib/rage/deferred/task.rb
|
129
138
|
- lib/rage/env.rb
|
130
139
|
- lib/rage/errors.rb
|
131
140
|
- lib/rage/ext/active_record/connection_pool.rb
|
132
141
|
- lib/rage/ext/setup.rb
|
133
142
|
- lib/rage/fiber.rb
|
134
143
|
- lib/rage/fiber_scheduler.rb
|
144
|
+
- lib/rage/hooks.rb
|
135
145
|
- lib/rage/logger/json_formatter.rb
|
136
146
|
- lib/rage/logger/logger.rb
|
137
147
|
- lib/rage/logger/text_formatter.rb
|
@@ -186,6 +196,7 @@ files:
|
|
186
196
|
- lib/rage/templates/config-initializers-.keep
|
187
197
|
- lib/rage/templates/config-routes.rb
|
188
198
|
- lib/rage/templates/config.ru
|
199
|
+
- lib/rage/templates/controller-template/controller.rb
|
189
200
|
- lib/rage/templates/db-templates/app-models-application_record.rb
|
190
201
|
- lib/rage/templates/db-templates/db-seeds.rb
|
191
202
|
- lib/rage/templates/db-templates/mysql/config-database.yml
|
@@ -213,7 +224,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
213
224
|
requirements:
|
214
225
|
- - ">="
|
215
226
|
- !ruby/object:Gem::Version
|
216
|
-
version: 3.
|
227
|
+
version: 3.2.0
|
217
228
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
218
229
|
requirements:
|
219
230
|
- - ">="
|