itsi-scheduler 0.2.10 → 0.2.11

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: 06da68bc85607dea16257e5043d45b1a9ea6f376c9ef8d41e2bda7f4a89a0dcb
4
- data.tar.gz: 2932d32895a5bef79abd2156248bd2eb089944d19810389c1ee1086c0406bf5f
3
+ metadata.gz: c057b5de1665276930d7c09f81ccc6e1b81419cf7cd9a4b3c04a08d3b6d0976d
4
+ data.tar.gz: 32fb526429c78f471eb248d3800dff138e7021aec6f95b13ee30ff4a4297a570
5
5
  SHA512:
6
- metadata.gz: 7419b864b913c1f80a50e8d3a7d061343382064bab38204e662a8e8eb4c3f5b31cbf26e473e74c7480c50bbfe04f792091c6960e903bbc3a7cfbb774a7f82e9e
7
- data.tar.gz: c94af7791e8da99fb1f174662587358a6994305650943372ba36635140eecd0b7b00c83bea33c4e1178f5d2e760acbb01ac7dd82c38b4de03ac1087df4656dc7
6
+ metadata.gz: c2304a02521484da65165d2f08632d9b52be536246ccefb5993b1715e7adcbe6cbc42fda820dffcd1e10bb1082b93ca9317e7aec6205cdfb735b3a6c933a63d5
7
+ data.tar.gz: d1c3f48ba6ba4c71694a5e0ee3f72ebb2b4229bbf4fe4cde8756ec5d6ed4d1c971c6e1e791c36b1f3ee7816e2db0a712aa70704b9c77ad9d2695021829c769c8
data/Cargo.lock CHANGED
@@ -213,7 +213,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
213
213
 
214
214
  [[package]]
215
215
  name = "itsi-scheduler"
216
- version = "0.2.10"
216
+ version = "0.2.11"
217
217
  dependencies = [
218
218
  "bytes",
219
219
  "derive_more",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-scheduler"
3
- version = "0.2.10"
3
+ version = "0.2.11"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "itsi-server"
3
- version = "0.2.10"
3
+ version = "0.2.11"
4
4
  edition = "2021"
5
5
  authors = ["Wouter Coppieters <wc@pico.net.nz>"]
6
6
  license = "MIT"
@@ -86,6 +86,8 @@ fn init(ruby: &Ruby) -> Result<()> {
86
86
  response.define_method("<<", method!(ItsiHttpResponse::send_frame, 1))?;
87
87
  response.define_method("write", method!(ItsiHttpResponse::send_frame, 1))?;
88
88
  response.define_method("read", method!(ItsiHttpResponse::recv_frame, 0))?;
89
+ response.define_method("flush", method!(ItsiHttpResponse::flush, 0))?;
90
+ response.define_method("closed?", method!(ItsiHttpResponse::is_closed, 0))?;
89
91
  response.define_method(
90
92
  "send_and_close",
91
93
  method!(ItsiHttpResponse::send_and_close, 1),
@@ -272,6 +272,14 @@ impl ItsiHttpResponse {
272
272
  // not implemented
273
273
  }
274
274
 
275
+ pub fn flush(&self) {
276
+ // no-op
277
+ }
278
+
279
+ pub fn is_closed(&self) -> bool {
280
+ self.data.response_writer.write().is_none()
281
+ }
282
+
275
283
  pub fn send_and_close(&self, frame: Bytes) -> MagnusResult<()> {
276
284
  let result = self.send_frame_into(ByteFrame::End(frame), &self.data.response_writer);
277
285
  self.data.response_writer.write().take();
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Itsi
4
4
  class Scheduler
5
- VERSION = "0.2.10"
5
+ VERSION = "0.2.11"
6
6
  end
7
7
  end
@@ -4,7 +4,35 @@ require_relative "scheduler/version"
4
4
  require_relative "scheduler/itsi_scheduler"
5
5
 
6
6
  module Itsi
7
+ module ScheduleUtils
8
+ def schedule(&block)
9
+ return to_enum(:schedule) unless block_given?
10
+
11
+ Object.schedule do
12
+ each { |item| Object.schedule { block.call(item) } }
13
+ end
14
+ end
15
+ end
16
+
7
17
  class Scheduler
18
+ def self.enable_schedule_keyword!
19
+ Object.define_method(:schedule) do |&blk|
20
+ result = nil
21
+ return result unless blk
22
+
23
+ if Fiber.scheduler.nil?
24
+ Thread.new do
25
+ Fiber.set_scheduler Itsi::Scheduler.new
26
+ Fiber.schedule { result = blk[] }
27
+ end.join
28
+ else
29
+ Fiber.schedule { result = blk[] }
30
+ end
31
+ result
32
+ end
33
+ Enumerable.include(ScheduleUtils)
34
+ end
35
+
8
36
  class Error < StandardError; end
9
37
 
10
38
  def self.resume_token
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: itsi-scheduler
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.10
4
+ version: 0.2.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wouter Coppieters
@@ -35,7 +35,6 @@ files:
35
35
  - ".rubocop.yml"
36
36
  - Cargo.lock
37
37
  - Cargo.toml
38
- - README.md
39
38
  - Rakefile
40
39
  - ext/itsi_acme/Cargo.toml
41
40
  - ext/itsi_acme/examples/high_level.rs
data/README.md DELETED
@@ -1,76 +0,0 @@
1
- ---
2
- title: Itsi Scheduler
3
- type: docs
4
- weight: 4
5
- sidebar:
6
- exclude: true
7
- ---
8
- <img src="itsi-scheduler-100.png" width="80px" style="display: block; margin-left: auto; margin-right: auto;">
9
-
10
- `Itsi Scheduler` is an implementation of a Ruby [Fiber Scheduler](https://docs.ruby-lang.org/en/3.2/Fiber/Scheduler.html).
11
-
12
- When combined with Itsi Server, you can write endpoints that look just like regular synchronous Ruby code. Behind the scenes, the scheduler will transparently pause and resume fibers to prevent threads from blocking, greatly increasing throughput for I/O-heavy workloads
13
-
14
- If you're purely after a lightweight, yet efficient Ruby scheduler,
15
- you can use Itsi Scheduler as a standalone scheduler for any Ruby application.
16
-
17
- Just use `Fiber.set_scheduler` to set an instance `Itsi::Scheduler` as a scheduler to opt in to this IO weaving behavior
18
- *automatically* for all blocking IO.
19
-
20
- ### Primer on Fiber Schedulers
21
-
22
- Fiber schedulers are a way to automatically manage the execution of non-blocking fibers in Ruby. A scheduler is responsible for the automatic pausing and resumption of Fibers based
23
- on whether or not they are awaiting IO operations.
24
- Ruby's Fiber scheduler implementation automatically invokes the current Fiber scheduler (if it exists) for each blocking operation, allowing it to seamlessly drive the execution of huge numbers of simultaneous non-blocking fibers
25
- while ensuring the main thread is never blocked on IO.
26
-
27
- This behind the scenes magic allows Ruby to provide async IO (just like we find in languages with `async/await` like `Rust`, `C#`, `JavaScript`) *but* with the added beauty
28
- that synchronous and asynchronous code is identical! (I.e. Ruby's functions are [colorless](https://journal.stuffwithstuff.com/2015/02/01/what-color-is-your-function/))
29
-
30
- ## Getting Started
31
- To install and use Itsi Scheduler follow the instructions below:
32
-
33
-
34
- ### 1 - Install Itsi Scheduler
35
-
36
- **Prerequisites**
37
-
38
- You'll need at least `build-essential` and `libclang-dev` installed to build Itsi on Linux.
39
- E.g.
40
- ```bash
41
- apt-get install build-essential libclang-dev
42
- ```
43
-
44
- Then use `gem` to install the Itsi package. This will in turn install both the
45
- `itsi-server` gem, and the `itsi-scheduler` gem.
46
-
47
-
48
- ```bash
49
- gem install itsi-scheduler
50
- ```
51
-
52
-
53
- ### 2 - Use Itsi Scheduler
54
-
55
- Great! You now have Itsi Scheduler installed.
56
- Now you can run code like this:
57
-
58
- ```ruby
59
- require 'itsi/scheduler'
60
- require 'socket'
61
- results = Thread.new do
62
- Fiber.set_scheduler Itsi::Scheduler.new
63
- results = []
64
- Fiber.schedule do
65
- results << Addrinfo.getaddrinfo("www.ruby-lang.org", 80, nil, :STREAM)
66
- end
67
- Fiber.schedule do
68
- results << Addrinfo.getaddrinfo("www.google.com", 80, nil, :STREAM)
69
- end
70
- results
71
- end.value
72
-
73
- puts results.map(&:inspect)
74
- ```
75
-
76
- to run many blocking operations simultaneously all while occupying only a single Ruby thread!