polyphony 0.48.0 → 0.49.0

Sign up to get free protection for your applications and to get access to all the features.
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: