polyphony 0.48.0 → 0.49.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: 3a699d313072b1beba17c900491dd2a4f454bc8faea69eb157634e98cba7ee90
4
- data.tar.gz: 3d8579b2c927c34876560ce878e960b9bc48a857ce43890dc069b4f0fa5ad75f
3
+ metadata.gz: 444ffbf8eb00cbd5e6948d6e3347e244fb8ea548aa1ad302d266e2f16c1a91b9
4
+ data.tar.gz: 2ac2f6ba1b51e71f1f138ad8eae665cc12e5458e836a0ef4f2df30d9ab95b679
5
5
  SHA512:
6
- metadata.gz: d6efca5f42f21fe25ab5e6064675c2806dcad9d86e2e80c908987fcce855dd520ab51c4913e5a9001d3e4a84880a6606d124fa46dedff7c2e437a1ef6e156a82
7
- data.tar.gz: 73ad6c59d4f7e9f8f0d317f480be1ba33c1a70dcf130a717693c2bb5a9ef3e226bfff3bdb635461b505bd2e9bbec7a2174c6a206bee2a94709ba9739ab087956
6
+ metadata.gz: 65924d13d191fc7c6d7b9fc2f7df997218396cf7ff9933564296ee50100441279387b01dc046797378973514dc45b25afd7eda92e19aac9dde3d7f2a13a9901e
7
+ data.tar.gz: a419d45a69c4a12a468277068ed792cc82d0384b2d620497c4c132fa27b9155ce05ce6662c062766ae5204c8c09a490bb1e95164c7a4bf0baa9f3166ac57d348
@@ -1,3 +1,7 @@
1
+ ## 0.49.0
2
+
3
+ - Implement `Polyphony::Timer` for performant timeouts
4
+
1
5
  ## 0.48.0
2
6
 
3
7
  - Implement graceful shutdown
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- polyphony (0.48.0)
4
+ polyphony (0.49.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2020 Sharon Rosner
3
+ Copyright (c) 2021 Sharon Rosner
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/TODO.md CHANGED
@@ -1,3 +1,5 @@
1
+ - Check segfault when doing lots of `cancel_after` calls
2
+
1
3
  - Override stock `SizedQueue` impl with Queue with capacity
2
4
 
3
5
  - Add support for `break` and `StopIteration` in all loops (with tests)
@@ -14,6 +14,7 @@ Thread.current.backend = Polyphony::Backend.new
14
14
  require_relative './polyphony/core/global_api'
15
15
  require_relative './polyphony/core/resource_pool'
16
16
  require_relative './polyphony/core/sync'
17
+ require_relative './polyphony/core/timer'
17
18
  require_relative './polyphony/net'
18
19
  require_relative './polyphony/adapters/process'
19
20
 
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Polyphony
4
+ # Implements a common timer for running multiple timeouts
5
+ class Timer
6
+ def initialize(resolution:)
7
+ @fiber = spin_loop(interval: resolution) { update }
8
+ @timeouts = {}
9
+ end
10
+
11
+ def stop
12
+ @fiber.stop
13
+ end
14
+
15
+ def cancel_after(duration, with_exception: Polyphony::Cancel)
16
+ fiber = Fiber.current
17
+ @timeouts[fiber] = {
18
+ duration: duration,
19
+ target_stamp: Time.now + duration,
20
+ exception: with_exception
21
+ }
22
+ yield
23
+ ensure
24
+ @timeouts.delete(fiber)
25
+ end
26
+
27
+ def move_on_after(duration, with_value: nil)
28
+ fiber = Fiber.current
29
+ @timeouts[fiber] = {
30
+ duration: duration,
31
+ target_stamp: Time.now + duration,
32
+ value: with_value
33
+ }
34
+ yield
35
+ rescue Polyphony::MoveOn => e
36
+ e.value
37
+ ensure
38
+ @timeouts.delete(fiber)
39
+ end
40
+
41
+ def reset
42
+ record = @timeouts[Fiber.current]
43
+ return unless record
44
+
45
+ record[:target_stamp] = Time.now + record[:duration]
46
+ end
47
+
48
+ private
49
+
50
+ def timeout_exception(record)
51
+ case (exception = record[:exception])
52
+ when Class then exception.new
53
+ when Array then exception[0].new(exception[1])
54
+ when nil then Polyphony::MoveOn.new(record[:value])
55
+ else RuntimeError.new(exception)
56
+ end
57
+ end
58
+
59
+ def update
60
+ now = Time.now
61
+ # elapsed = nil
62
+ @timeouts.each do |fiber, record|
63
+ next if record[:target_stamp] > now
64
+
65
+ exception = timeout_exception(record)
66
+ # (elapsed ||= []) << fiber
67
+ fiber.schedule exception
68
+ end
69
+ # elapsed&.each { |f| @timeouts.delete(f) }
70
+ end
71
+ end
72
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Polyphony
4
- VERSION = '0.48.0'
4
+ VERSION = '0.49.0'
5
5
  end
@@ -639,7 +639,6 @@ class FiberTest < MiniTest::Test
639
639
  i.close
640
640
  f.await
641
641
  rescue Exception => e
642
- trace e
643
642
  o << e.class.name
644
643
  o.close
645
644
  end
@@ -63,14 +63,15 @@ class HTTPClientTest < MiniTest::Test
63
63
  require 'json'
64
64
 
65
65
  def test_http
66
- res = HTTParty.get('http://worldtimeapi.org/api/timezone/Europe/Paris')
66
+ res = HTTParty.get('http://ipinfo.io/')
67
+
67
68
  response = JSON.load(res.body)
68
- assert_equal "CET", response['abbreviation']
69
+ assert_equal 'https://ipinfo.io/missingauth', response['readme']
69
70
  end
70
71
 
71
72
  def test_https
72
- res = HTTParty.get('https://worldtimeapi.org/api/timezone/Europe/Paris')
73
+ res = HTTParty.get('https://ipinfo.io/')
73
74
  response = JSON.load(res.body)
74
- assert_equal "CET", response['abbreviation']
75
+ assert_equal 'https://ipinfo.io/missingauth', response['readme']
75
76
  end
76
77
  end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ class TimerMoveOnAfterTest < MiniTest::Test
6
+ def setup
7
+ @timer = Polyphony::Timer.new(resolution: 0.01)
8
+ end
9
+
10
+ def teardown
11
+ @timer.stop
12
+ end
13
+
14
+ def test_move_on_after
15
+ t0 = Time.now
16
+ v = @timer.move_on_after(0.1) do
17
+ sleep 1
18
+ :foo
19
+ end
20
+ t1 = Time.now
21
+
22
+ assert_in_range 0.1..0.15, t1 - t0
23
+ assert_nil v
24
+ end
25
+
26
+ def test_move_on_after_with_value
27
+ t0 = Time.now
28
+ v = @timer.move_on_after(0.01, with_value: :bar) do
29
+ sleep 1
30
+ :foo
31
+ end
32
+ t1 = Time.now
33
+
34
+ assert_in_range 0.01..0.02, t1 - t0
35
+ assert_equal :bar, v
36
+ end
37
+
38
+ def test_move_on_after_with_reset
39
+ t0 = Time.now
40
+ v = @timer.move_on_after(0.01, with_value: :moved_on) do
41
+ sleep 0.007
42
+ @timer.reset
43
+ sleep 0.007
44
+ nil
45
+ end
46
+ t1 = Time.now
47
+
48
+ assert_nil v
49
+ assert_in_range 0.014..0.02, t1 - t0
50
+ end
51
+ end
52
+
53
+ class CancelAfterTest < MiniTest::Test
54
+ def setup
55
+ @timer = Polyphony::Timer.new(resolution: 0.01)
56
+ end
57
+
58
+ def teardown
59
+ @timer.stop
60
+ end
61
+
62
+ def test_cancel_after
63
+ t0 = Time.now
64
+
65
+ assert_raises Polyphony::Cancel do
66
+ @timer.cancel_after(0.01) do
67
+ sleep 1
68
+ :foo
69
+ end
70
+ end
71
+ t1 = Time.now
72
+ assert_in_range 0.01..0.02, t1 - t0
73
+ end
74
+
75
+ def test_cancel_after_with_reset
76
+ t0 = Time.now
77
+ @timer.cancel_after(0.01) do
78
+ sleep 0.007
79
+ @timer.reset
80
+ sleep 0.007
81
+ end
82
+ t1 = Time.now
83
+ assert_in_range 0.014..0.024, t1 - t0
84
+ end
85
+
86
+ class CustomException < Exception
87
+ end
88
+
89
+ def test_cancel_after_with_custom_exception
90
+ assert_raises CustomException do
91
+ @timer.cancel_after(0.01, with_exception: CustomException) do
92
+ sleep 1
93
+ :foo
94
+ end
95
+ end
96
+
97
+ begin
98
+ err = nil
99
+ @timer.cancel_after(0.01, with_exception: [CustomException, 'custom message']) do
100
+ sleep 1
101
+ :foo
102
+ end
103
+ rescue Exception => err
104
+ ensure
105
+ assert_kind_of CustomException, err
106
+ assert_equal 'custom message', err.message
107
+ end
108
+
109
+
110
+ begin
111
+ e = nil
112
+ @timer.cancel_after(0.01, with_exception: 'foo') do
113
+ sleep 1
114
+ :foo
115
+ end
116
+ rescue => e
117
+ ensure
118
+ assert_kind_of RuntimeError, e
119
+ assert_equal 'foo', e.message
120
+ end
121
+ end
122
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: polyphony
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.48.0
4
+ version: 0.49.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-01-05 00:00:00.000000000 Z
11
+ date: 2021-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -476,6 +476,7 @@ files:
476
476
  - lib/polyphony/core/sync.rb
477
477
  - lib/polyphony/core/thread_pool.rb
478
478
  - lib/polyphony/core/throttler.rb
479
+ - lib/polyphony/core/timer.rb
479
480
  - lib/polyphony/extensions/core.rb
480
481
  - lib/polyphony/extensions/debug.rb
481
482
  - lib/polyphony/extensions/fiber.rb
@@ -510,6 +511,7 @@ files:
510
511
  - test/test_thread.rb
511
512
  - test/test_thread_pool.rb
512
513
  - test/test_throttler.rb
514
+ - test/test_timer.rb
513
515
  - test/test_trace.rb
514
516
  homepage: https://digital-fabric.github.io/polyphony
515
517
  licenses: