hakuban 0.6.5 → 0.7.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/bin/{hakuban-thread-engine → hakuban-engine} +7 -6
- data/bin/hakuban-observer +39 -35
- data/lib/hakuban/contract.rb +196 -0
- data/lib/hakuban/descriptor.rb +90 -0
- data/lib/hakuban/engine.rb +3 -3
- data/lib/hakuban/exchange.rb +75 -0
- data/lib/hakuban/ffi-object.rb +132 -0
- data/lib/hakuban/ffi.rb +217 -141
- data/lib/hakuban/logger.rb +16 -0
- data/lib/hakuban/object_state.rb +106 -0
- data/lib/hakuban/object_state_sink.rb +64 -0
- data/lib/hakuban/object_state_stream.rb +39 -0
- data/lib/hakuban/stream.rb +119 -0
- data/lib/hakuban/tokio-websocket-connector.rb +32 -0
- data/lib/hakuban/version.rb +1 -1
- data/lib/hakuban.rb +21 -6
- metadata +29 -10
- data/lib/hakuban/async.rb +0 -38
- data/lib/hakuban/event-queue.rb +0 -75
- data/lib/hakuban/hakuban.rb +0 -545
- data/lib/hakuban/manager.rb +0 -398
- data/lib/hakuban/thread.rb +0 -35
@@ -0,0 +1,119 @@
|
|
1
|
+
|
2
|
+
module Hakuban
|
3
|
+
|
4
|
+
module Stream
|
5
|
+
|
6
|
+
def each(*args,**kwargs,&block)
|
7
|
+
StreamEnumerator.new(self,false,false,false,args,kwargs).call_or_return(&block)
|
8
|
+
end
|
9
|
+
|
10
|
+
class KilledOnNext < Exception; end
|
11
|
+
|
12
|
+
#TODO: meh
|
13
|
+
class StreamEnumerator
|
14
|
+
|
15
|
+
def initialize(stream, without_implicit_drop, async, kill_on_next, args, kwargs)
|
16
|
+
@stream, @without_implicit_drop, @async, @kill_on_next, @args, @kwargs = stream, without_implicit_drop, async, kill_on_next, args, kwargs
|
17
|
+
end
|
18
|
+
|
19
|
+
def async(*args,**kwargs,&block)
|
20
|
+
StreamEnumerator.new(@stream, @without_implicit_drop, :async, @kill_on_next, @args+args, @kwargs.merge(kwargs)).call_or_return(&block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def thread(*args,**kwargs,&block)
|
24
|
+
StreamEnumerator.new(@stream, @without_implicit_drop, :thread, @kill_on_next, @args+args, @kwargs.merge(kwargs)).call_or_return(&block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def without_implicit_drop(*args,**kwargs,&block)
|
28
|
+
StreamEnumerator.new(@stream, true, @async, @kill_on_next, @args+args, @kwargs.merge(kwargs)).call_or_return(&block)
|
29
|
+
end
|
30
|
+
|
31
|
+
def kill_on_next(*args,**kwargs,&block)
|
32
|
+
StreamEnumerator.new(@stream, @without_implicit_drop, @async, true, @args+args, @kwargs.merge(kwargs)).call_or_return(&block)
|
33
|
+
end
|
34
|
+
|
35
|
+
def call_or_return(&block)
|
36
|
+
if block
|
37
|
+
Thread.handle_interrupt(Object => :never) {
|
38
|
+
begin
|
39
|
+
to_kill = nil
|
40
|
+
Thread.handle_interrupt(Object => :immediate) {
|
41
|
+
while new_item = @stream.next
|
42
|
+
case @async
|
43
|
+
when false
|
44
|
+
sync_call(new_item, block)
|
45
|
+
when :async
|
46
|
+
if @kill_on_next
|
47
|
+
if to_kill
|
48
|
+
to_kill.stop
|
49
|
+
to_kill.wait
|
50
|
+
end
|
51
|
+
end
|
52
|
+
to_kill = Async(new_item) { |_task, item|
|
53
|
+
sync_call(item, block)
|
54
|
+
}
|
55
|
+
when :thread
|
56
|
+
if @kill_on_next
|
57
|
+
if to_kill
|
58
|
+
to_kill.raise KilledOnNext.new
|
59
|
+
to_kill.value
|
60
|
+
end
|
61
|
+
end
|
62
|
+
to_kill = Thread.new(new_item) { |item|
|
63
|
+
sync_call(item, block)
|
64
|
+
}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
case @async
|
69
|
+
when false
|
70
|
+
when :async
|
71
|
+
if @kill_on_next
|
72
|
+
if to_kill
|
73
|
+
to_kill.stop
|
74
|
+
to_kill.wait
|
75
|
+
end
|
76
|
+
end
|
77
|
+
when :thread
|
78
|
+
if @kill_on_next
|
79
|
+
if to_kill
|
80
|
+
to_kill.raise KilledOnNext.new
|
81
|
+
to_kill.value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
}
|
86
|
+
ensure
|
87
|
+
#TODO: should we kill still-running sub-tasks here, or await? or maybe kill on exception, and await otherwise?
|
88
|
+
end
|
89
|
+
}
|
90
|
+
else
|
91
|
+
self
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
private def sync_call(item, block)
|
96
|
+
if @without_implicit_drop
|
97
|
+
begin
|
98
|
+
block.call(item, *@args, **@kwargs)
|
99
|
+
rescue KilledOnNext
|
100
|
+
end
|
101
|
+
else
|
102
|
+
Thread.handle_interrupt(Object => :never) {
|
103
|
+
begin
|
104
|
+
Thread.handle_interrupt(Object => :immediate) {
|
105
|
+
block.call(item, *@args, **@kwargs)
|
106
|
+
}
|
107
|
+
rescue KilledOnNext
|
108
|
+
ensure
|
109
|
+
item.drop
|
110
|
+
end
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'hakuban/ffi-object.rb'
|
2
|
+
|
3
|
+
module Hakuban
|
4
|
+
|
5
|
+
class Tokio
|
6
|
+
|
7
|
+
@@pointer = nil
|
8
|
+
|
9
|
+
def Tokio.init(workers_count=0)
|
10
|
+
Hakuban::hakuban_initialize
|
11
|
+
@@pointer ||= FFI::hakuban_tokio_init_multi_thread(0)
|
12
|
+
end
|
13
|
+
|
14
|
+
def Tokio.pointer
|
15
|
+
Tokio.init if not @@pointer
|
16
|
+
@@pointer
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
class WebsocketConnector < FFIObject
|
23
|
+
|
24
|
+
def initialize(local_exchange, url, &block)
|
25
|
+
pointer = local_exchange.with_pointer { |local_exchange_pointer| FFI::hakuban_tokio_websocket_connector_new(Tokio.pointer, local_exchange_pointer, url) }.unwrap
|
26
|
+
initialize_pointer(pointer, :hakuban_tokio_websocket_connector_drop, nil)
|
27
|
+
self.do_and_drop_or_return(&block)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/hakuban/version.rb
CHANGED
data/lib/hakuban.rb
CHANGED
@@ -1,10 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative "hakuban/version"
|
4
|
-
require_relative "hakuban/hakuban"
|
5
|
-
require_relative "hakuban/engine"
|
6
|
-
#require_relative "hakuban/async"
|
7
|
-
#require_relative "hakuban/thread"
|
8
|
-
|
9
3
|
module Hakuban
|
4
|
+
|
5
|
+
def self.hakuban_initialize
|
6
|
+
require_relative 'hakuban/ffi.rb'
|
7
|
+
end
|
8
|
+
|
10
9
|
end
|
10
|
+
|
11
|
+
|
12
|
+
require_relative 'hakuban/contract.rb'
|
13
|
+
require_relative 'hakuban/descriptor.rb'
|
14
|
+
require_relative "hakuban/engine"
|
15
|
+
require_relative 'hakuban/exchange.rb'
|
16
|
+
require_relative 'hakuban/ffi-object.rb'
|
17
|
+
require_relative 'hakuban/logger.rb'
|
18
|
+
require_relative 'hakuban/object_state_sink.rb'
|
19
|
+
require_relative 'hakuban/object_state_stream.rb'
|
20
|
+
require_relative 'hakuban/object_state.rb'
|
21
|
+
require_relative 'hakuban/tokio-websocket-connector.rb'
|
22
|
+
require_relative "hakuban/version"
|
23
|
+
|
24
|
+
|
25
|
+
#TODO: error classes
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hakuban
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- yunta
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,6 +24,20 @@ dependencies:
|
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '3.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: simplecov
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.21'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.21'
|
27
41
|
- !ruby/object:Gem::Dependency
|
28
42
|
name: ffi
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -71,23 +85,28 @@ email:
|
|
71
85
|
- maciej.blomberg@mikoton.com
|
72
86
|
executables:
|
73
87
|
- hakuban-observer
|
74
|
-
- hakuban-
|
88
|
+
- hakuban-engine
|
75
89
|
extensions: []
|
76
90
|
extra_rdoc_files: []
|
77
91
|
files:
|
78
92
|
- MIT-LICENSE
|
79
93
|
- README.md
|
80
94
|
- Rakefile
|
95
|
+
- bin/hakuban-engine
|
81
96
|
- bin/hakuban-observer
|
82
|
-
- bin/hakuban-thread-engine
|
83
97
|
- lib/hakuban.rb
|
84
|
-
- lib/hakuban/
|
98
|
+
- lib/hakuban/contract.rb
|
99
|
+
- lib/hakuban/descriptor.rb
|
85
100
|
- lib/hakuban/engine.rb
|
86
|
-
- lib/hakuban/
|
101
|
+
- lib/hakuban/exchange.rb
|
102
|
+
- lib/hakuban/ffi-object.rb
|
87
103
|
- lib/hakuban/ffi.rb
|
88
|
-
- lib/hakuban/
|
89
|
-
- lib/hakuban/
|
90
|
-
- lib/hakuban/
|
104
|
+
- lib/hakuban/logger.rb
|
105
|
+
- lib/hakuban/object_state.rb
|
106
|
+
- lib/hakuban/object_state_sink.rb
|
107
|
+
- lib/hakuban/object_state_stream.rb
|
108
|
+
- lib/hakuban/stream.rb
|
109
|
+
- lib/hakuban/tokio-websocket-connector.rb
|
91
110
|
- lib/hakuban/version.rb
|
92
111
|
homepage: https://gitlab.com/yunta/hakuban-ruby
|
93
112
|
licenses:
|
@@ -108,7 +127,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
108
127
|
- !ruby/object:Gem::Version
|
109
128
|
version: '0'
|
110
129
|
requirements: []
|
111
|
-
rubygems_version: 3.
|
130
|
+
rubygems_version: 3.3.26
|
112
131
|
signing_key:
|
113
132
|
specification_version: 4
|
114
133
|
summary: Ruby binding for Hakuban library
|
data/lib/hakuban/async.rb
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
require 'hakuban'
|
2
|
-
require 'hakuban/manager'
|
3
|
-
require 'async'
|
4
|
-
|
5
|
-
module Hakuban
|
6
|
-
|
7
|
-
class AsyncObjectManager < ObjectManager
|
8
|
-
|
9
|
-
def async_run
|
10
|
-
Async { yield }
|
11
|
-
end
|
12
|
-
|
13
|
-
def async_join(task)
|
14
|
-
task.wait
|
15
|
-
end
|
16
|
-
|
17
|
-
def async_stop(task)
|
18
|
-
task.stop
|
19
|
-
end
|
20
|
-
|
21
|
-
def async_filter_out_stop_exception
|
22
|
-
yield
|
23
|
-
rescue Async::Stop
|
24
|
-
nil
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
class ObjectManagerBuilder
|
31
|
-
|
32
|
-
def with_async(&block)
|
33
|
-
build(AsyncObjectManager, block)
|
34
|
-
end
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
end
|
data/lib/hakuban/event-queue.rb
DELETED
@@ -1,75 +0,0 @@
|
|
1
|
-
#TODO: rebuild to handle event squashing on rust side
|
2
|
-
|
3
|
-
require 'ostruct'
|
4
|
-
|
5
|
-
|
6
|
-
module Hakuban
|
7
|
-
|
8
|
-
class Event < OpenStruct; end
|
9
|
-
|
10
|
-
class ObjectDescriptorCallbackEventQueue
|
11
|
-
|
12
|
-
def initialize(pointer)
|
13
|
-
@events_pointer = ::FFI::AutoPointer.new(pointer, proc { |ptr| FFI.hakuban_object_descriptor_events_return(ptr) })
|
14
|
-
end
|
15
|
-
|
16
|
-
|
17
|
-
# WARNING: this callback may be run from a separate, non-ruby, thread
|
18
|
-
def callback_register(&callback)
|
19
|
-
ffi_callback = proc { |_userdata, ffi_descriptor, ffi_action|
|
20
|
-
action = Hakuban::action_int_to_symbol(ffi_action)
|
21
|
-
descriptor = ObjectDescriptor.from_ffi(ffi_descriptor)
|
22
|
-
callback.call(descriptor, action)
|
23
|
-
}
|
24
|
-
@callback_pointer = ::FFI::AutoPointer.new(
|
25
|
-
FFI::hakuban_object_descriptor_events_callback_register(@events_pointer, ffi_callback, ::FFI::Pointer::NULL),
|
26
|
-
proc { |ptr| FFI::hakuban_object_descriptor_events_callback_unregister(ptr) }
|
27
|
-
)
|
28
|
-
end
|
29
|
-
|
30
|
-
|
31
|
-
def callback_unregister
|
32
|
-
@callback_pointer.free
|
33
|
-
@callback_pointer = nil
|
34
|
-
end
|
35
|
-
|
36
|
-
|
37
|
-
def drop
|
38
|
-
@events_pointer.free
|
39
|
-
@events_pointer = nil
|
40
|
-
end
|
41
|
-
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
class ObjectDescriptorEventQueue
|
46
|
-
|
47
|
-
def initialize(contract)
|
48
|
-
@contract = contract
|
49
|
-
@queue = Queue.new
|
50
|
-
@ffi_callback = proc { |descriptor, action|
|
51
|
-
@queue << Hakuban::Event.new(action: action, descriptor: descriptor)
|
52
|
-
}
|
53
|
-
@ffi_events = @contract.new_callback_event_queue
|
54
|
-
@ffi_events.callback_register(&@ffi_callback)
|
55
|
-
end
|
56
|
-
|
57
|
-
|
58
|
-
#def push(event)
|
59
|
-
# @queue << event
|
60
|
-
#end
|
61
|
-
|
62
|
-
|
63
|
-
def next_event; next_change; end
|
64
|
-
def next_change
|
65
|
-
@queue.pop
|
66
|
-
end
|
67
|
-
|
68
|
-
|
69
|
-
def close
|
70
|
-
@queue.close
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
end
|