zapp 0.2.1 → 0.2.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (119) hide show
  1. checksums.yaml +4 -4
  2. data/lib/zapp/configuration.rb +9 -1
  3. data/lib/zapp/http_context/request.rb +2 -2
  4. data/lib/zapp/logger/base.rb +103 -0
  5. data/lib/zapp/logger.rb +20 -57
  6. data/lib/zapp/server.rb +9 -4
  7. data/lib/zapp/socket_pipe/receiver.rb +0 -8
  8. data/lib/zapp/version.rb +1 -1
  9. data/lib/zapp/worker/request_processor.rb +27 -32
  10. data/lib/zapp/worker.rb +5 -6
  11. data/lib/zapp/worker_pool.rb +6 -5
  12. data/lib/zapp.rb +5 -2
  13. metadata +5 -109
  14. data/.circleci/config.yml +0 -21
  15. data/.gitignore +0 -13
  16. data/.rspec +0 -3
  17. data/.rubocop.yml +0 -48
  18. data/.ruby-version +0 -1
  19. data/Gemfile +0 -13
  20. data/Gemfile.lock +0 -112
  21. data/Guardfile +0 -23
  22. data/LICENSE.txt +0 -21
  23. data/README.md +0 -91
  24. data/Rakefile +0 -8
  25. data/examples/rails-app/.browserslistrc +0 -1
  26. data/examples/rails-app/.gitattributes +0 -10
  27. data/examples/rails-app/.gitignore +0 -40
  28. data/examples/rails-app/.ruby-version +0 -1
  29. data/examples/rails-app/Gemfile +0 -58
  30. data/examples/rails-app/Gemfile.lock +0 -255
  31. data/examples/rails-app/Rakefile +0 -8
  32. data/examples/rails-app/app/assets/config/manifest.js +0 -2
  33. data/examples/rails-app/app/assets/images/.keep +0 -0
  34. data/examples/rails-app/app/assets/stylesheets/application.css +0 -15
  35. data/examples/rails-app/app/channels/application_cable/channel.rb +0 -6
  36. data/examples/rails-app/app/channels/application_cable/connection.rb +0 -6
  37. data/examples/rails-app/app/controllers/application_controller.rb +0 -4
  38. data/examples/rails-app/app/controllers/concerns/.keep +0 -0
  39. data/examples/rails-app/app/helpers/application_helper.rb +0 -4
  40. data/examples/rails-app/app/javascript/channels/consumer.js +0 -6
  41. data/examples/rails-app/app/javascript/channels/index.js +0 -5
  42. data/examples/rails-app/app/javascript/packs/application.js +0 -13
  43. data/examples/rails-app/app/jobs/application_job.rb +0 -9
  44. data/examples/rails-app/app/mailers/application_mailer.rb +0 -6
  45. data/examples/rails-app/app/models/application_record.rb +0 -5
  46. data/examples/rails-app/app/models/concerns/.keep +0 -0
  47. data/examples/rails-app/app/views/layouts/application.html.erb +0 -16
  48. data/examples/rails-app/app/views/layouts/mailer.html.erb +0 -13
  49. data/examples/rails-app/app/views/layouts/mailer.text.erb +0 -1
  50. data/examples/rails-app/babel.config.js +0 -82
  51. data/examples/rails-app/bin/bundle +0 -118
  52. data/examples/rails-app/bin/rails +0 -7
  53. data/examples/rails-app/bin/rake +0 -7
  54. data/examples/rails-app/bin/setup +0 -38
  55. data/examples/rails-app/bin/spring +0 -16
  56. data/examples/rails-app/bin/webpack +0 -21
  57. data/examples/rails-app/bin/webpack-dev-server +0 -21
  58. data/examples/rails-app/bin/yarn +0 -19
  59. data/examples/rails-app/bin/zapp +0 -1
  60. data/examples/rails-app/config/application.rb +0 -24
  61. data/examples/rails-app/config/boot.rb +0 -6
  62. data/examples/rails-app/config/cable.yml +0 -10
  63. data/examples/rails-app/config/credentials.yml.enc +0 -1
  64. data/examples/rails-app/config/database.yml +0 -25
  65. data/examples/rails-app/config/environment.rb +0 -7
  66. data/examples/rails-app/config/environments/development.rb +0 -78
  67. data/examples/rails-app/config/environments/production.rb +0 -122
  68. data/examples/rails-app/config/environments/test.rb +0 -62
  69. data/examples/rails-app/config/initializers/application_controller_renderer.rb +0 -9
  70. data/examples/rails-app/config/initializers/assets.rb +0 -16
  71. data/examples/rails-app/config/initializers/backtrace_silencers.rb +0 -10
  72. data/examples/rails-app/config/initializers/content_security_policy.rb +0 -31
  73. data/examples/rails-app/config/initializers/cookies_serializer.rb +0 -7
  74. data/examples/rails-app/config/initializers/filter_parameter_logging.rb +0 -8
  75. data/examples/rails-app/config/initializers/inflections.rb +0 -17
  76. data/examples/rails-app/config/initializers/mime_types.rb +0 -5
  77. data/examples/rails-app/config/initializers/permissions_policy.rb +0 -12
  78. data/examples/rails-app/config/initializers/wrap_parameters.rb +0 -16
  79. data/examples/rails-app/config/locales/en.yml +0 -33
  80. data/examples/rails-app/config/puma.rb +0 -45
  81. data/examples/rails-app/config/routes.rb +0 -5
  82. data/examples/rails-app/config/spring.rb +0 -8
  83. data/examples/rails-app/config/storage.yml +0 -34
  84. data/examples/rails-app/config/webpack/development.js +0 -5
  85. data/examples/rails-app/config/webpack/environment.js +0 -3
  86. data/examples/rails-app/config/webpack/production.js +0 -5
  87. data/examples/rails-app/config/webpack/test.js +0 -5
  88. data/examples/rails-app/config/webpacker.yml +0 -92
  89. data/examples/rails-app/config/zapp.rb +0 -10
  90. data/examples/rails-app/config.ru +0 -7
  91. data/examples/rails-app/db/seeds.rb +0 -8
  92. data/examples/rails-app/lib/assets/.keep +0 -0
  93. data/examples/rails-app/lib/tasks/.keep +0 -0
  94. data/examples/rails-app/log/.keep +0 -0
  95. data/examples/rails-app/package.json +0 -17
  96. data/examples/rails-app/postcss.config.js +0 -12
  97. data/examples/rails-app/public/404.html +0 -67
  98. data/examples/rails-app/public/422.html +0 -67
  99. data/examples/rails-app/public/500.html +0 -66
  100. data/examples/rails-app/public/apple-touch-icon-precomposed.png +0 -0
  101. data/examples/rails-app/public/apple-touch-icon.png +0 -0
  102. data/examples/rails-app/public/favicon.ico +0 -0
  103. data/examples/rails-app/public/robots.txt +0 -1
  104. data/examples/rails-app/storage/.keep +0 -0
  105. data/examples/rails-app/test/application_system_test_case.rb +0 -7
  106. data/examples/rails-app/test/channels/application_cable/connection_test.rb +0 -15
  107. data/examples/rails-app/test/controllers/.keep +0 -0
  108. data/examples/rails-app/test/fixtures/files/.keep +0 -0
  109. data/examples/rails-app/test/helpers/.keep +0 -0
  110. data/examples/rails-app/test/integration/.keep +0 -0
  111. data/examples/rails-app/test/mailers/.keep +0 -0
  112. data/examples/rails-app/test/models/.keep +0 -0
  113. data/examples/rails-app/test/system/.keep +0 -0
  114. data/examples/rails-app/test/test_helper.rb +0 -17
  115. data/examples/rails-app/tmp/.keep +0 -0
  116. data/examples/rails-app/tmp/pids/.keep +0 -0
  117. data/examples/rails-app/vendor/.keep +0 -0
  118. data/examples/rails-app/yarn.lock +0 -6973
  119. data/zapp.gemspec +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '083c3deaea0cc22f0bd269afbccdd556bf66743771aca04f63f125809c934473'
4
- data.tar.gz: cd3a771ca1d0e898ddaa99c71b741412e4be8370286ec484b2059317cb632802
3
+ metadata.gz: d92db6f0faeb0316e5493676b97ed1566b65e14753e39423f8c73e8365aa7908
4
+ data.tar.gz: 253b76825620d5b55840a8e5b6686068bf7049271b093a9efb5a862d5040922d
5
5
  SHA512:
6
- metadata.gz: 227f3dc9ce4c2cac931c89f2a3bca81f90f91031a78998258befb02515ee5eb1af386741646bdecc14e82649cc5cc876f360cbfb8a01bf84e119b062ab3a0eea
7
- data.tar.gz: ffa29c579b1621eca0093e2c3d9a4f02975aa3be6a81aa17348aff7a7f5f54cecf4ea8aeb7829c6a821d4691c2ac9a2cd2d0be33204f2a02b1fd163b5c6990e3
6
+ metadata.gz: 3c1e015b962b63b8b92420746df6c5a6e470d9b9721b2b0ab4967b2b260e1fdce32baad057c048140391f3155f723626a0b959e86620d66a2318bea2c7beac81
7
+ data.tar.gz: 24967c889e62d3235fd162a1b6568bd63b6a72755b63e73910ac4b326fd92a5dd4026291d3f1e847e62f6b06cb9fc5e377c5061632651323576c52088c778dcc
@@ -12,6 +12,7 @@ module Zapp
12
12
  :parallelism,
13
13
  :threads_per_worker,
14
14
  :logger_class,
15
+ :logger_out_io,
15
16
  :log_requests,
16
17
  :log_uncaught_errors,
17
18
  :host,
@@ -33,6 +34,7 @@ module Zapp
33
34
 
34
35
  # Default logging behavior
35
36
  logger_class: Zapp::Logger,
37
+ logger_out_io: $stdout,
36
38
  log_requests: true,
37
39
  log_uncaught_errors: true,
38
40
 
@@ -72,7 +74,7 @@ module Zapp
72
74
  @app = new unless new.nil?
73
75
 
74
76
  @app ||= begin
75
- raise(Zapp::ZapError, "Missing rackup file '#{rackup_file}'") unless File.exist?(rackup_file)
77
+ raise(Zapp::ZappError, "Missing rackup file '#{rackup_file}'") unless File.exist?(rackup_file)
76
78
 
77
79
  rack_app, = rack_builder.parse_file(rackup_file)
78
80
 
@@ -98,6 +100,12 @@ module Zapp
98
100
  @logger_class = new
99
101
  end
100
102
 
103
+ def logger_out_io(new = nil)
104
+ return @logger_out_io if new.nil?
105
+
106
+ @logger_out_io = new
107
+ end
108
+
101
109
  def log_requests(new = nil)
102
110
  return @log_requests if new.nil?
103
111
 
@@ -9,7 +9,7 @@ module Zapp
9
9
  attr_reader(:raw, :data, :body)
10
10
 
11
11
  # Request parsing is done threaded, but not in separate Ractors.
12
- # So we allocate an HTTP parser per thread and assigns it to this hash key on Thread.current
12
+ # So we allocate an HTTP parser per thread and assign it to this hash key in Thread.current
13
13
  PARSER_THREAD_HASH_KEY = "PUMA_PARSER_INSTANCE"
14
14
 
15
15
  def initialize(socket:)
@@ -19,7 +19,7 @@ module Zapp
19
19
 
20
20
  parser.execute(data, raw, 0)
21
21
 
22
- @body = Zapp::InputStream.new(string: "parser.body")
22
+ @body = Zapp::InputStream.new(string: parser.body)
23
23
 
24
24
  parser.reset
25
25
  end
@@ -0,0 +1,103 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Zapp
4
+ class Logger
5
+ # Base contains all the logging functionality and is included both as class and instance methods of Zap::Logger
6
+ # This allows logging without creating new instances,
7
+ # while allowing Ractors to create their own instances for thread safety
8
+ module Base
9
+ attr_writer(:level, :prefix)
10
+
11
+ LEVELS = { TRACE: 0, DEBUG: 1, INFO: 2, WARN: 3, ERROR: 4 }.freeze
12
+
13
+ FROZEN_ENV = ENV.map { |k, v| [k.freeze, v.freeze] }
14
+ .to_h.freeze
15
+
16
+ # The hash key in Ractor.current that stores the mutex for writing to output
17
+ OUT_IO_MUTEX_KEY = "ZAPP_LOGGER_OUT_IO_MUTEX"
18
+
19
+ def trace(msg) = log("TRACE", msg)
20
+
21
+ def debug(msg) = log("DEBUG", msg)
22
+
23
+ def info(msg) = log("INFO", msg)
24
+
25
+ def warn(msg) = log("WARN", msg)
26
+
27
+ def error(msg) = log("ERROR", msg)
28
+
29
+ def level
30
+ @level ||= begin
31
+ log_level = FROZEN_ENV["LOG_LEVEL"]
32
+
33
+ if log_level == "" || log_level.nil?
34
+ LEVELS[:DEBUG]
35
+ else
36
+ resolved_level = LEVELS[log_level.upcase.to_sym]
37
+
38
+ if resolved_level.nil?
39
+ raise(
40
+ Zapp::ZappError,
41
+ "Invalid log level '#{log_level.upcase}', must be one of [#{LEVELS.keys.join(', ')}]"
42
+ )
43
+ end
44
+
45
+ resolved_level
46
+ end
47
+ end
48
+ end
49
+
50
+ def log(current_level, msg, **_tags)
51
+ return unless level <= LEVELS[current_level.to_sym]
52
+
53
+ write("--- #{prefix} [#{current_level}] #{msg}\n")
54
+ end
55
+
56
+ def flush
57
+ writing_thread_pool.wait_for_termination(0.1)
58
+
59
+ out_io_mutex.synchronize do
60
+ out.flush
61
+ end
62
+ end
63
+
64
+ # @param new_out [IO]
65
+ def out=(new_out)
66
+ @out = new_out
67
+ end
68
+
69
+ protected
70
+
71
+ # @return [IO]
72
+ def out
73
+ @out ||= Zapp.config.logger_out_io
74
+ end
75
+
76
+ # @return [String]
77
+ def prefix = @prefix ||= Ractor.current.name
78
+
79
+ def write(msg)
80
+ writing_thread_pool.post do
81
+ out_io_mutex.synchronize do
82
+ out.print(msg)
83
+ end
84
+ end
85
+ end
86
+
87
+ # We really just use this as a queue
88
+ # TODO: There's probably a smarter way of doing this with less overhead,
89
+ # TODO: or maybe we should just actually write logs multi-threaded
90
+ def writing_thread_pool
91
+ @writing_thread_pool ||= Concurrent::ThreadPoolExecutor.new(
92
+ min_threads: 1,
93
+ max_threads: 1,
94
+ max_queue: 100
95
+ )
96
+ end
97
+
98
+ def out_io_mutex
99
+ Ractor.current[OUT_IO_MUTEX_KEY] ||= Thread::Mutex.new
100
+ end
101
+ end
102
+ end
103
+ end
data/lib/zapp/logger.rb CHANGED
@@ -1,74 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative("logger/base")
4
+
3
5
  module Zapp
4
- # The default logger for zap
6
+ # The default logger for Zapp
5
7
  class Logger
6
- # Base contains all the logging functionality and is included both as class and instance methods of Zap::Logger
7
- # This allows logging without creating new instances,
8
- # while allowing Ractors to create their own instances for thread safety
9
- module Base
10
- attr_writer(:level, :prefix)
11
-
12
- LEVELS = { TRACE: 0, DEBUG: 1, INFO: 2, WARN: 3, ERROR: 4 }.freeze
13
-
14
- FROZEN_ENV = ENV.map { |k, v| [k.freeze, v.freeze] }
15
- .to_h.freeze
16
-
17
- def trace(msg)
18
- log("TRACE", msg)
19
- end
20
-
21
- def debug(msg)
22
- log("DEBUG", msg)
23
- end
8
+ include(Zapp::Logger::Base)
24
9
 
25
- def info(msg)
26
- log("INFO", msg)
27
- end
10
+ def initialize
11
+ yield(self) if block_given?
12
+ end
28
13
 
29
- def warn(msg)
30
- log("WARN", msg)
31
- end
14
+ class << self
15
+ # The hash key in Ractor.current that stores the global Zapp::Logger instance
16
+ GLOBAL_INSTANCE_KEY = "ZAPP_LOGGER_INSTANCE"
32
17
 
33
- def error(msg)
34
- log("ERROR", msg)
18
+ def instance
19
+ Ractor.current[GLOBAL_INSTANCE_KEY] ||= new
35
20
  end
36
21
 
37
- def level
38
- @level ||= begin
39
- log_level = FROZEN_ENV["LOG_LEVEL"]
40
-
41
- if log_level == "" || log_level.nil?
42
- LEVELS[:DEBUG]
43
- else
44
- resolved_level = LEVELS[log_level.upcase.to_sym]
45
-
46
- if resolved_level.nil?
47
- raise(
48
- Zapp::ZappError,
49
- "Invalid log level '#{log_level.upcase}', must be one of [#{LEVELS.keys.join(', ')}]"
50
- )
51
- end
22
+ private
52
23
 
53
- resolved_level
54
- end
24
+ def method_missing(symbol, *args)
25
+ if respond_to_missing?(symbol)
26
+ instance.public_send(symbol, *args)
27
+ else
28
+ super
55
29
  end
56
30
  end
57
31
 
58
- def log(current_level, msg, **_tags)
59
- puts("--- #{@prefix} [#{current_level}] #{msg}") if level <= LEVELS[current_level.to_sym]
32
+ def respond_to_missing?(symbol, include_private = false)
33
+ instance.respond_to?(symbol) || super(symbol, include_private)
60
34
  end
61
35
  end
62
- include(Zapp::Logger::Base)
63
-
64
- def initialize
65
- yield(self) if block_given?
66
- end
67
-
68
- class << self
69
- include(Zapp::Logger::Base)
70
- end
71
36
  end
72
37
  end
73
-
74
- Zapp::Logger.prefix = "Zapp"
data/lib/zapp/server.rb CHANGED
@@ -6,12 +6,15 @@ module Zapp
6
6
  attr_reader(:worker_pool, :socket_pipe_receiver)
7
7
 
8
8
  def initialize
9
+ # Ensure config.ru file is loaded just once by main ractor
10
+ Zapp.config.app
11
+
9
12
  @socket_pipe = Zapp::Pipe.new
10
13
  @context_pipe = Zapp::Pipe.new
11
14
 
12
15
  @socket_pipe_receiver = Zapp::SocketPipe::Receiver.new(pipe: @socket_pipe)
13
16
 
14
- @worker_pool = Zapp::WorkerPool.new(app: Zapp.config.app, socket_pipe: @socket_pipe, context_pipe: @context_pipe)
17
+ @worker_pool = Zapp::WorkerPool.new(socket_pipe: @socket_pipe, context_pipe: @context_pipe)
15
18
  end
16
19
 
17
20
  def run
@@ -38,16 +41,17 @@ module Zapp
38
41
  Zapp::Logger.info("Received signal #{err.class.name}") unless err.nil?
39
42
  Zapp::Logger.info("Gracefully shutting down workers, allowing request processing to finish")
40
43
 
41
- socket_pipe_receiver.drain
42
44
  worker_pool.drain
43
45
 
44
46
  Zapp::Logger.info("Done. See you next time!")
47
+ Zapp::Logger.flush
45
48
  end
46
49
 
47
50
  private
48
51
 
49
52
  def log_start
50
- Zapp::Logger.info("
53
+ Zapp::Logger.info(
54
+ "
51
55
  ⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡
52
56
  ⚡ ███████╗ █████╗ ██████╗ ██████╗ ⚡
53
57
  ⚡ ╚══███╔╝██╔══██╗██╔══██╗██╔══██╗ ⚡
@@ -56,7 +60,8 @@ module Zapp
56
60
  ⚡ ███████╗██║ ██║██║ ██║ ⚡
57
61
  ⚡ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ ⚡
58
62
  ⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡⚡
59
- ")
63
+ "
64
+ )
60
65
  Zapp::Logger.info("Zapp version: #{Zapp::VERSION}")
61
66
  Zapp::Logger.info("Environment: #{Zapp.config.mode}")
62
67
  Zapp::Logger.info("Serving: #{Zapp.config.env[Rack::RACK_URL_SCHEME]}://#{Zapp.config.host}:#{Zapp.config.port}")
@@ -19,14 +19,6 @@ module Zapp
19
19
  def take
20
20
  Ractor.select(pipe, raw_tcp_pipe)[1]
21
21
  end
22
-
23
- def drain
24
- Thread.new do
25
- loop do
26
- take
27
- end
28
- end
29
- end
30
22
  end
31
23
  end
32
24
  end
data/lib/zapp/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Zapp
4
- VERSION = "0.2.1"
4
+ VERSION = "0.2.4"
5
5
  end
@@ -4,11 +4,9 @@ module Zapp
4
4
  class Worker < Ractor
5
5
  # Processes HTTP requests
6
6
  class RequestProcessor
7
- attr_reader(:app, :config, :socket_pipe_sender, :context_pipe)
7
+ attr_reader(:socket_pipe_sender, :context_pipe)
8
8
 
9
- def initialize(context_pipe:, socket_pipe:, app:, config:)
10
- @app = app
11
- @config = config
9
+ def initialize(context_pipe:, socket_pipe:)
12
10
  @socket_pipe_sender = Zapp::SocketPipe::Sender.new(pipe: socket_pipe)
13
11
  @context_pipe = context_pipe
14
12
  end
@@ -16,26 +14,24 @@ module Zapp
16
14
  def loop
17
15
  while (context = context_pipe.take)
18
16
  if context == Zapp::WorkerPool::SIGNALS[:EXIT]
19
- logger.trace("Received exit signal, shutting down")
20
- thread_pool.shutdown
17
+ Zapp::Logger.trace("Received exit signal, shutting down")
18
+ shutdown
21
19
  break
22
20
  end
23
21
 
22
+ process = lambda {
23
+ process(context: context)
24
+ }
24
25
 
25
- process = lambda {
26
- process(context: context)
27
- }
28
-
29
- if config.log_requests
30
- log_request_time(context: context, &process)
31
- else
32
- process.call
33
- end
34
-
35
- # We send sockets that the client hasn't closed yet,
36
- # back to the main ractor for HTTP request parsing again
37
- socket_pipe_sender.push(context.socket) unless context.client_closed?
26
+ if Zapp.config.log_requests
27
+ log_request_time(context: context, &process)
28
+ else
29
+ process.call
30
+ end
38
31
 
32
+ # We send sockets that the client hasn't closed yet,
33
+ # back to the main ractor for HTTP request parsing again
34
+ socket_pipe_sender.push(context.socket) unless context.client_closed?
39
35
  end
40
36
  end
41
37
 
@@ -43,16 +39,16 @@ module Zapp
43
39
 
44
40
  # Processes an HTTP request
45
41
  def process(context:)
46
- env = prepare_env(data: context.req.data, body: context.req.body, env: config.env.dup)
42
+ env = prepare_env(data: context.req.data, body: context.req.body, env: Zapp.config.env.dup)
47
43
 
48
- status, headers, response_body_stream = @app.call(env)
44
+ status, headers, response_body_stream = Zapp.config.app.call(env)
49
45
 
50
46
  response_body = body_stream_to_string(response_body_stream)
51
47
 
52
48
  context.res.write(data: response_body, status: status, headers: headers)
53
49
  rescue StandardError => e
54
50
  context.res.write(data: "An unexpected error occurred", status: 500, headers: {})
55
- logger.error("#{e}\n\n#{e.backtrace&.join(",\n")}") if config.log_uncaught_errors
51
+ Zapp::Logger.error("#{e}\n\n#{e.backtrace&.join(",\n")}") if Zapp.config.log_uncaught_errors
56
52
  end
57
53
 
58
54
  # Merges HTTP data and body into the env to be passed to the rack app
@@ -79,7 +75,7 @@ module Zapp
79
75
  path = context.req.data["PATH_INFO"]
80
76
  status = context.res.status
81
77
 
82
- logger.info(
78
+ Zapp::Logger.info(
83
79
  "#{method} #{path} - Completed in #{request_time}ms with status #{status}"
84
80
  )
85
81
  end
@@ -96,19 +92,18 @@ module Zapp
96
92
  response_body
97
93
  end
98
94
 
95
+ def shutdown
96
+ Zapp::Logger.flush
97
+ thread_pool.shutdown
98
+ end
99
+
99
100
  def thread_pool
100
101
  @thread_pool ||= Concurrent::ThreadPoolExecutor.new(
101
- min_threads: config.threads_per_worker,
102
- max_threads: config.threads_per_worker,
103
- max_queue: 1000,
102
+ min_threads: Zapp.config.threads_per_worker,
103
+ max_threads: Zapp.config.threads_per_worker,
104
+ max_queue: 1000
104
105
  )
105
106
  end
106
-
107
- def logger
108
- @logger ||= config.logger_class.new do |l|
109
- l.prefix = Ractor.current.name
110
- end
111
- end
112
107
  end
113
108
  end
114
109
  end
data/lib/zapp/worker.rb CHANGED
@@ -6,19 +6,18 @@ module Zapp
6
6
  # One worker processing requests in parallel
7
7
  class Worker < Ractor
8
8
  class << self
9
- def new(context_pipe:, socket_pipe:, app:, index:)
9
+ def new(context_pipe:, socket_pipe:, index:)
10
10
  super(
11
11
  context_pipe,
12
12
  socket_pipe,
13
- app,
14
13
  Zapp.config.dup,
15
14
  name: name(index)
16
- ) do |context_pipe, socket_pipe, app, config|
15
+ ) do |context_pipe, socket_pipe, config|
16
+ Ractor.current[Zapp::RACTOR_CONFIG_KEY] = config
17
+
17
18
  processor = Zapp::Worker::RequestProcessor.new(
18
19
  socket_pipe: socket_pipe,
19
- context_pipe: context_pipe,
20
- app: app,
21
- config: config
20
+ context_pipe: context_pipe
22
21
  )
23
22
 
24
23
  processor.loop
@@ -9,14 +9,13 @@ module Zapp
9
9
  EXIT: :exit
10
10
  }.freeze
11
11
 
12
- def initialize(app:, context_pipe:, socket_pipe:)
12
+ def initialize(context_pipe:, socket_pipe:)
13
13
  @context_pipe = context_pipe
14
14
  @workers = []
15
15
  Zapp.config.parallelism.times do |i|
16
16
  @workers << Worker.new(
17
17
  context_pipe: context_pipe,
18
18
  socket_pipe: socket_pipe,
19
- app: app,
20
19
  index: i
21
20
  )
22
21
  end
@@ -30,9 +29,11 @@ module Zapp
30
29
  # Finishes processing of all requests and shuts down workers
31
30
  def drain
32
31
  Zapp.config.parallelism.times { process(context: SIGNALS[:EXIT]) }
33
- workers.map(&:terminate)
34
- rescue Ractor::ClosedError
35
- # Ractor has already exited
32
+ workers.map do |w|
33
+ w.terminate
34
+ rescue Ractor::ClosedError
35
+ # Ractor has already exited
36
+ end
36
37
  end
37
38
  end
38
39
  end
data/lib/zapp.rb CHANGED
@@ -11,11 +11,14 @@ require("rack")
11
11
  module Zapp
12
12
  class ZappError < StandardError; end
13
13
 
14
+ # The hash key in Ractor.current that stores the global Zapp::Configuration instance
15
+ RACTOR_CONFIG_KEY = "ZAPP_CONFIG"
16
+
14
17
  class << self
15
18
  def config(reset: false)
16
- @config = Zapp::Configuration.new if reset
19
+ Ractor.current[RACTOR_CONFIG_KEY] = Zapp::Configuration.new if reset
17
20
 
18
- @config ||= Zapp::Configuration.new
21
+ Ractor.current[RACTOR_CONFIG_KEY] ||= Zapp::Configuration.new
19
22
  end
20
23
 
21
24
  def configure
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: zapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mathias H Steffensen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-07-10 00:00:00.000000000 Z
11
+ date: 2022-07-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -97,116 +97,12 @@ dependencies:
97
97
  description:
98
98
  email:
99
99
  - mathiashsteffensen@protonmail.com
100
- executables: []
100
+ executables:
101
+ - zapp
101
102
  extensions: []
102
103
  extra_rdoc_files: []
103
104
  files:
104
- - ".circleci/config.yml"
105
- - ".gitignore"
106
- - ".rspec"
107
- - ".rubocop.yml"
108
- - ".ruby-version"
109
- - Gemfile
110
- - Gemfile.lock
111
- - Guardfile
112
- - LICENSE.txt
113
- - README.md
114
- - Rakefile
115
105
  - bin/zapp
116
- - examples/rails-app/.browserslistrc
117
- - examples/rails-app/.gitattributes
118
- - examples/rails-app/.gitignore
119
- - examples/rails-app/.ruby-version
120
- - examples/rails-app/Gemfile
121
- - examples/rails-app/Gemfile.lock
122
- - examples/rails-app/Rakefile
123
- - examples/rails-app/app/assets/config/manifest.js
124
- - examples/rails-app/app/assets/images/.keep
125
- - examples/rails-app/app/assets/stylesheets/application.css
126
- - examples/rails-app/app/channels/application_cable/channel.rb
127
- - examples/rails-app/app/channels/application_cable/connection.rb
128
- - examples/rails-app/app/controllers/application_controller.rb
129
- - examples/rails-app/app/controllers/concerns/.keep
130
- - examples/rails-app/app/helpers/application_helper.rb
131
- - examples/rails-app/app/javascript/channels/consumer.js
132
- - examples/rails-app/app/javascript/channels/index.js
133
- - examples/rails-app/app/javascript/packs/application.js
134
- - examples/rails-app/app/jobs/application_job.rb
135
- - examples/rails-app/app/mailers/application_mailer.rb
136
- - examples/rails-app/app/models/application_record.rb
137
- - examples/rails-app/app/models/concerns/.keep
138
- - examples/rails-app/app/views/layouts/application.html.erb
139
- - examples/rails-app/app/views/layouts/mailer.html.erb
140
- - examples/rails-app/app/views/layouts/mailer.text.erb
141
- - examples/rails-app/babel.config.js
142
- - examples/rails-app/bin/bundle
143
- - examples/rails-app/bin/rails
144
- - examples/rails-app/bin/rake
145
- - examples/rails-app/bin/setup
146
- - examples/rails-app/bin/spring
147
- - examples/rails-app/bin/webpack
148
- - examples/rails-app/bin/webpack-dev-server
149
- - examples/rails-app/bin/yarn
150
- - examples/rails-app/bin/zapp
151
- - examples/rails-app/config.ru
152
- - examples/rails-app/config/application.rb
153
- - examples/rails-app/config/boot.rb
154
- - examples/rails-app/config/cable.yml
155
- - examples/rails-app/config/credentials.yml.enc
156
- - examples/rails-app/config/database.yml
157
- - examples/rails-app/config/environment.rb
158
- - examples/rails-app/config/environments/development.rb
159
- - examples/rails-app/config/environments/production.rb
160
- - examples/rails-app/config/environments/test.rb
161
- - examples/rails-app/config/initializers/application_controller_renderer.rb
162
- - examples/rails-app/config/initializers/assets.rb
163
- - examples/rails-app/config/initializers/backtrace_silencers.rb
164
- - examples/rails-app/config/initializers/content_security_policy.rb
165
- - examples/rails-app/config/initializers/cookies_serializer.rb
166
- - examples/rails-app/config/initializers/filter_parameter_logging.rb
167
- - examples/rails-app/config/initializers/inflections.rb
168
- - examples/rails-app/config/initializers/mime_types.rb
169
- - examples/rails-app/config/initializers/permissions_policy.rb
170
- - examples/rails-app/config/initializers/wrap_parameters.rb
171
- - examples/rails-app/config/locales/en.yml
172
- - examples/rails-app/config/puma.rb
173
- - examples/rails-app/config/routes.rb
174
- - examples/rails-app/config/spring.rb
175
- - examples/rails-app/config/storage.yml
176
- - examples/rails-app/config/webpack/development.js
177
- - examples/rails-app/config/webpack/environment.js
178
- - examples/rails-app/config/webpack/production.js
179
- - examples/rails-app/config/webpack/test.js
180
- - examples/rails-app/config/webpacker.yml
181
- - examples/rails-app/config/zapp.rb
182
- - examples/rails-app/db/seeds.rb
183
- - examples/rails-app/lib/assets/.keep
184
- - examples/rails-app/lib/tasks/.keep
185
- - examples/rails-app/log/.keep
186
- - examples/rails-app/package.json
187
- - examples/rails-app/postcss.config.js
188
- - examples/rails-app/public/404.html
189
- - examples/rails-app/public/422.html
190
- - examples/rails-app/public/500.html
191
- - examples/rails-app/public/apple-touch-icon-precomposed.png
192
- - examples/rails-app/public/apple-touch-icon.png
193
- - examples/rails-app/public/favicon.ico
194
- - examples/rails-app/public/robots.txt
195
- - examples/rails-app/storage/.keep
196
- - examples/rails-app/test/application_system_test_case.rb
197
- - examples/rails-app/test/channels/application_cable/connection_test.rb
198
- - examples/rails-app/test/controllers/.keep
199
- - examples/rails-app/test/fixtures/files/.keep
200
- - examples/rails-app/test/helpers/.keep
201
- - examples/rails-app/test/integration/.keep
202
- - examples/rails-app/test/mailers/.keep
203
- - examples/rails-app/test/models/.keep
204
- - examples/rails-app/test/system/.keep
205
- - examples/rails-app/test/test_helper.rb
206
- - examples/rails-app/tmp/.keep
207
- - examples/rails-app/tmp/pids/.keep
208
- - examples/rails-app/vendor/.keep
209
- - examples/rails-app/yarn.lock
210
106
  - lib/rack/handler/zapp.rb
211
107
  - lib/zapp.rb
212
108
  - lib/zapp/cli.rb
@@ -216,6 +112,7 @@ files:
216
112
  - lib/zapp/http_context/response.rb
217
113
  - lib/zapp/input_stream.rb
218
114
  - lib/zapp/logger.rb
115
+ - lib/zapp/logger/base.rb
219
116
  - lib/zapp/parser.rb
220
117
  - lib/zapp/pipe.rb
221
118
  - lib/zapp/server.rb
@@ -225,7 +122,6 @@ files:
225
122
  - lib/zapp/worker.rb
226
123
  - lib/zapp/worker/request_processor.rb
227
124
  - lib/zapp/worker_pool.rb
228
- - zapp.gemspec
229
125
  homepage: https://github.com/mathiashsteffensen/zapp
230
126
  licenses:
231
127
  - MIT