ciri 0.0.0 → 0.0.1
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/.gitmodules +14 -0
- data/.rspec +2 -1
- data/.travis.yml +11 -4
- data/Gemfile.lock +3 -0
- data/README.md +44 -34
- data/Rakefile +47 -4
- data/ciri.gemspec +13 -12
- data/docker/Base +34 -0
- data/lib/ciri/actor.rb +223 -0
- data/lib/ciri/chain.rb +293 -0
- data/lib/ciri/chain/block.rb +47 -0
- data/lib/ciri/chain/header.rb +62 -0
- data/lib/ciri/chain/transaction.rb +145 -0
- data/lib/ciri/crypto.rb +58 -5
- data/lib/ciri/db/backend/memory.rb +68 -0
- data/lib/ciri/db/backend/rocks.rb +104 -0
- data/lib/ciri/db/backend/rocks_db.rb +278 -0
- data/lib/ciri/devp2p/peer.rb +10 -2
- data/lib/ciri/devp2p/protocol.rb +11 -3
- data/lib/ciri/devp2p/protocol_io.rb +6 -3
- data/lib/ciri/devp2p/rlpx.rb +1 -0
- data/lib/ciri/devp2p/rlpx/encryption_handshake.rb +1 -1
- data/lib/ciri/devp2p/rlpx/frame_io.rb +1 -1
- data/lib/ciri/devp2p/rlpx/message.rb +4 -4
- data/lib/ciri/devp2p/server.rb +14 -13
- data/lib/ciri/eth.rb +33 -0
- data/lib/ciri/eth/peer.rb +64 -0
- data/lib/ciri/eth/protocol_manage.rb +122 -0
- data/lib/ciri/eth/protocol_messages.rb +158 -0
- data/lib/ciri/eth/synchronizer.rb +188 -0
- data/lib/ciri/ethash.rb +123 -0
- data/lib/ciri/evm.rb +140 -0
- data/lib/ciri/evm/account.rb +50 -0
- data/lib/ciri/evm/block_info.rb +31 -0
- data/lib/ciri/evm/forks/frontier.rb +183 -0
- data/lib/ciri/evm/instruction.rb +92 -0
- data/lib/ciri/evm/machine_state.rb +81 -0
- data/lib/ciri/evm/op.rb +536 -0
- data/lib/ciri/evm/serialize.rb +60 -0
- data/lib/ciri/evm/sub_state.rb +64 -0
- data/lib/ciri/evm/vm.rb +379 -0
- data/lib/ciri/forks.rb +38 -0
- data/lib/ciri/forks/frontier.rb +43 -0
- data/lib/ciri/key.rb +7 -1
- data/lib/ciri/pow.rb +95 -0
- data/lib/ciri/rlp.rb +3 -53
- data/lib/ciri/rlp/decode.rb +100 -40
- data/lib/ciri/rlp/encode.rb +95 -34
- data/lib/ciri/rlp/serializable.rb +61 -91
- data/lib/ciri/types/address.rb +70 -0
- data/lib/ciri/types/errors.rb +36 -0
- data/lib/ciri/utils.rb +45 -13
- data/lib/ciri/utils/lib_c.rb +46 -0
- data/lib/ciri/utils/logger.rb +99 -0
- data/lib/ciri/utils/number.rb +67 -0
- data/lib/ciri/version.rb +1 -1
- metadata +67 -7
- data/lib/ciri/devp2p/actor.rb +0 -224
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: abe8d78482df9ed72840456def4146338c14d14fe797d8a97ff8bbe1a93f1243
|
4
|
+
data.tar.gz: 65f245e4ec4aa14c2747745976a350ceee764c08f8e010e6586e6c8ba5a57227
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 478a4f654e958caa242c46881120d7737a7b74a72f142a05e29ea83fa32daef22d0a63832f9fc4ef649c9a8860e3be5226a376304d52de78ac1ec1e9ad1005b2
|
7
|
+
data.tar.gz: 556717e91e6dd17e22aeadd6c9f322ffd7d95540bbfcb9bfa775acdafa63a31e149bba971dd4e03ea935eba24d5f3a4f77bde2ba52c0bbe2e2f32b872c86afad
|
data/.gitmodules
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
[submodule "secp256k1"]
|
2
|
+
path = secp256k1
|
3
|
+
url = https://github.com/bitcoin-core/secp256k1.git
|
4
|
+
[submodule "rocksdb"]
|
5
|
+
path = rocksdb
|
6
|
+
url = https://github.com/facebook/rocksdb.git
|
7
|
+
[submodule "ethash"]
|
8
|
+
path = ethash
|
9
|
+
url = https://github.com/ciri-ethereum/ethash.git
|
10
|
+
branch = shared_library
|
11
|
+
[submodule "fixtures"]
|
12
|
+
path = fixtures
|
13
|
+
url = https://github.com/ethereum/tests.git
|
14
|
+
branch = develop
|
data/.rspec
CHANGED
data/.travis.yml
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
-
sudo:
|
1
|
+
sudo: required
|
2
2
|
language: ruby
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
|
4
|
+
services:
|
5
|
+
- docker
|
6
|
+
|
7
|
+
before_install:
|
8
|
+
- docker pull ciriethereum/base:latest
|
9
|
+
- gem install rake
|
10
|
+
|
11
|
+
script:
|
12
|
+
- rake docker:test
|
data/Gemfile.lock
CHANGED
@@ -5,6 +5,8 @@ PATH
|
|
5
5
|
bitcoin-secp256k1 (~> 0.4.0)
|
6
6
|
concurrent-ruby (~> 1.0.5)
|
7
7
|
digest-sha3 (~> 1.1.0)
|
8
|
+
ffi (~> 1.9.23)
|
9
|
+
lru_redux (~> 1.1.0)
|
8
10
|
snappy (~> 0.0.17)
|
9
11
|
|
10
12
|
GEM
|
@@ -16,6 +18,7 @@ GEM
|
|
16
18
|
diff-lcs (1.3)
|
17
19
|
digest-sha3 (1.1.0)
|
18
20
|
ffi (1.9.23)
|
21
|
+
lru_redux (1.1.0)
|
19
22
|
rake (10.3.2)
|
20
23
|
rspec (3.7.0)
|
21
24
|
rspec-core (~> 3.7.0)
|
data/README.md
CHANGED
@@ -1,49 +1,59 @@
|
|
1
1
|
Ciri
|
2
2
|
===============
|
3
|
+
[](https://travis-ci.org/ciri-ethereum/ciri)
|
4
|
+
[](https://gitter.im/ciri-ethereum/Lobby)
|
3
5
|
|
4
6
|
Ciri project intent to implement a full feature set ethereum client.
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
* [ ] RLPX
|
9
|
-
* [x] HandShake
|
10
|
-
* [ ] Server
|
11
|
-
* [ ] Node Discovery
|
12
|
-
* [x] RLP
|
13
|
-
* [ ] Eth Protocol
|
14
|
-
* [x] HandShake
|
15
|
-
* [ ] Ethereum Sub-protocol
|
16
|
-
* [ ] Block Chain
|
17
|
-
* [ ] Chain Syncing
|
18
|
-
* [ ] EVM
|
19
|
-
* [ ] Mining
|
20
|
-
* [ ] Consensus Algorithm
|
21
|
-
* [ ] POW
|
22
|
-
* [ ] POS
|
23
|
-
* [ ] Web3 RPC
|
24
|
-
* [ ] CLI
|
25
|
-
|
26
|
-
### Install
|
8
|
+
It aims to be a feature complete, long maintained and stable ethereum client.
|
9
|
+
As you see it'is still under development.
|
27
10
|
|
28
|
-
|
29
|
-
|
30
|
-
|
11
|
+
Talk to me on [gitter](https://gitter.im/ciri-ethereum/Lobby) if you interesting in this project or want to contributing.
|
12
|
+
|
13
|
+
See [projects](https://github.com/ciri-ethereum/ciri/projects) and [milestones](https://github.com/ciri-ethereum/ciri/milestones) for current development status.
|
31
14
|
|
32
|
-
|
15
|
+
Installation
|
16
|
+
---------------
|
33
17
|
|
34
|
-
|
35
|
-
require 'ciri'
|
36
|
-
puts Ciri::Version
|
37
|
-
```
|
18
|
+
See [develop](#develop) section
|
38
19
|
|
39
|
-
|
20
|
+
Usage
|
21
|
+
---------------
|
40
22
|
|
41
23
|
`ciri -h`
|
42
24
|
|
43
|
-
|
25
|
+
Develop
|
26
|
+
---------------
|
27
|
+
|
28
|
+
Ciri depends on [rocksdb](https://github.com/facebook/rocksdb), [secp256k1](https://github.com/bitcoin-core/secp256k1), [ethash](https://github.com/ethereum/ethash) and [snappy](https://github.com/google/snappy).
|
29
|
+
|
30
|
+
It's recommended to use docker to handle dependencies:
|
31
|
+
``` bash
|
32
|
+
# make sure we have installed docker, ruby and rake
|
33
|
+
docker -v
|
34
|
+
gem install rake
|
35
|
+
|
36
|
+
# pull Ciri base image
|
37
|
+
rake docker:pull_base
|
38
|
+
# run tests
|
39
|
+
rake docker:test
|
40
|
+
# open a shell for develop
|
41
|
+
rake docker:shell
|
42
|
+
|
43
|
+
# cool, type 'rake -T' see other supported tasks
|
44
|
+
```
|
45
|
+
|
46
|
+
Otherwise you need install these libraries manually (remember check [docker](/docker) directory for hint).
|
47
|
+
|
48
|
+
then run:
|
49
|
+
`bundle install && bundle exec rake`
|
50
|
+
|
51
|
+
Documentation
|
52
|
+
---------------
|
44
53
|
|
45
|
-
[YARD documentation](https://www.rubydoc.info/github/
|
54
|
+
[YARD documentation](https://www.rubydoc.info/github/ciri-ethereum/ciri/master)
|
46
55
|
|
47
|
-
|
56
|
+
Authors
|
57
|
+
---------------
|
48
58
|
|
49
|
-
[Jiang Jinyang](https://justjjy.com)
|
59
|
+
* [Jiang Jinyang](https://justjjy.com) (jjyruby@gmail.com)
|
data/Rakefile
CHANGED
@@ -1,6 +1,49 @@
|
|
1
|
-
|
2
|
-
require "
|
1
|
+
begin
|
2
|
+
require "bundler/gem_tasks"
|
3
|
+
rescue LoadError
|
4
|
+
puts "bundler not installed, use 'gem install bundler' to install"
|
5
|
+
end
|
3
6
|
|
4
|
-
|
7
|
+
begin
|
8
|
+
require "rspec/core/rake_task"
|
9
|
+
RSpec::Core::RakeTask.new(:spec)
|
10
|
+
task :default => :spec
|
11
|
+
rescue LoadError
|
12
|
+
nil
|
13
|
+
end
|
5
14
|
|
6
|
-
|
15
|
+
namespace :docker do
|
16
|
+
base_image = 'ciriethereum/base'
|
17
|
+
|
18
|
+
desc 'pull base docker image'
|
19
|
+
task :pull_base do
|
20
|
+
system("docker pull #{base_image}:latest")
|
21
|
+
end
|
22
|
+
|
23
|
+
desc 'build base docker image, rerun this task after updated Gemfile or Dockerfile'
|
24
|
+
task :build_base do
|
25
|
+
system("git submodule init && git submodule update")
|
26
|
+
system("docker build . -f docker/Base -t #{base_image}:latest")
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'open Ciri develop container shell'
|
30
|
+
task :shell do
|
31
|
+
container_name = 'ciri-develop'
|
32
|
+
if system("docker inspect #{container_name} > /dev/null")
|
33
|
+
system("docker start -i #{container_name}")
|
34
|
+
else
|
35
|
+
puts "start a new develop container: #{container_name}"
|
36
|
+
system("docker run -v `pwd`:/app -it --name #{container_name} #{base_image}:latest bash")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
desc 'run tests in docker'
|
41
|
+
task :test do
|
42
|
+
system("docker run -v `pwd`:/app --rm #{base_image}:latest rspec -t ~slow_tests")
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'run all tests(include slow tests) in docker'
|
46
|
+
task :"test:all" do
|
47
|
+
system("docker run -v `pwd`:/app --rm #{base_image}:latest rspec")
|
48
|
+
end
|
49
|
+
end
|
data/ciri.gemspec
CHANGED
@@ -1,26 +1,27 @@
|
|
1
|
-
|
2
1
|
lib = File.expand_path("../lib", __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require "ciri/version"
|
5
4
|
|
6
5
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
6
|
+
spec.name = "ciri"
|
7
|
+
spec.version = Ciri::VERSION
|
8
|
+
spec.authors = ["Jiang Jinyang"]
|
9
|
+
spec.email = ["jjyruby@gmail.com"]
|
11
10
|
|
12
|
-
spec.summary
|
13
|
-
spec.description
|
14
|
-
spec.homepage
|
15
|
-
spec.license
|
11
|
+
spec.summary = %q{Ciri ethereum client.}
|
12
|
+
spec.description = %q{Ciri project intent to implement a full feature set ethereum client.}
|
13
|
+
spec.homepage = "https://github.com/ciri-ethereum/ciri"
|
14
|
+
spec.license = "MIT"
|
16
15
|
|
17
|
-
spec.files
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
18
17
|
f.match(%r{^(test|spec|features)/})
|
19
18
|
end
|
20
|
-
spec.bindir
|
21
|
-
spec.executables
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) {|f| File.basename(f)}
|
22
21
|
spec.require_paths = ["lib"]
|
23
22
|
|
23
|
+
spec.add_dependency 'ffi', '~> 1.9.23'
|
24
|
+
spec.add_dependency 'lru_redux', '~> 1.1.0'
|
24
25
|
spec.add_dependency 'digest-sha3', '~> 1.1.0'
|
25
26
|
spec.add_dependency 'bitcoin-secp256k1', '~> 0.4.0'
|
26
27
|
spec.add_dependency 'concurrent-ruby', '~> 1.0.5'
|
data/docker/Base
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
FROM ruby:2.5.1
|
2
|
+
MAINTAINER Jiang Jinyang<jjyruby@gmail.com>
|
3
|
+
|
4
|
+
RUN apt-get update -y
|
5
|
+
RUN apt-get install -y cmake
|
6
|
+
|
7
|
+
# install bitcoin secp256k1
|
8
|
+
COPY ./secp256k1 /build/secp256k1
|
9
|
+
WORKDIR /build/secp256k1
|
10
|
+
RUN ./autogen.sh
|
11
|
+
RUN ./configure --enable-module-recovery --enable-experimental --enable-module-ecdh
|
12
|
+
RUN make && make install
|
13
|
+
|
14
|
+
# install ethash
|
15
|
+
COPY ./ethash /build/ethash
|
16
|
+
WORKDIR /build/ethash/src/libethash
|
17
|
+
RUN cmake CMakeLists.txt
|
18
|
+
RUN make install
|
19
|
+
|
20
|
+
# install RocksDB
|
21
|
+
RUN apt-get install -y libgflags-dev zlib1g-dev libbz2-dev liblz4-dev libzstd-dev
|
22
|
+
COPY ./rocksdb /build/rocksdb
|
23
|
+
WORKDIR /build/rocksdb
|
24
|
+
RUN make shared_lib
|
25
|
+
RUN make install-shared
|
26
|
+
|
27
|
+
# install snappy
|
28
|
+
RUN apt-get install -y libsnappy-dev
|
29
|
+
|
30
|
+
WORKDIR /app
|
31
|
+
COPY . /app
|
32
|
+
|
33
|
+
# bundle
|
34
|
+
RUN bundle install
|
data/lib/ciri/actor.rb
ADDED
@@ -0,0 +1,223 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright (c) 2018, by Jiang Jinyang. <https://justjjy.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
|
24
|
+
require 'logger'
|
25
|
+
|
26
|
+
module Ciri
|
27
|
+
|
28
|
+
# simple actor model implementation
|
29
|
+
# Example:
|
30
|
+
#
|
31
|
+
# class Hello
|
32
|
+
# include Actor
|
33
|
+
#
|
34
|
+
# def say_hello
|
35
|
+
# puts 'hello world'
|
36
|
+
# 'hello world'
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# actor = Hello.new()
|
41
|
+
# # start actor loop
|
42
|
+
# actor.start
|
43
|
+
# # push message to actor inbox
|
44
|
+
# actor << :say_hello
|
45
|
+
# # push message and wait until get response
|
46
|
+
# actor.call(:say_hello).value
|
47
|
+
#
|
48
|
+
# # raise error
|
49
|
+
# actor.call(:hello).value # NoMethodError
|
50
|
+
#
|
51
|
+
# # stop actor
|
52
|
+
# actor.send_stop
|
53
|
+
# actor.wait
|
54
|
+
#
|
55
|
+
module Actor
|
56
|
+
|
57
|
+
LOGGER = Logger.new(STDERR, datetime_format: '%Y-%m-%d %H:%M:%S', level: Logger::INFO)
|
58
|
+
|
59
|
+
# future, use this to wait actor msg respond
|
60
|
+
class Future
|
61
|
+
def initialize
|
62
|
+
@value = nil
|
63
|
+
@done = false
|
64
|
+
@queue = Queue.new
|
65
|
+
end
|
66
|
+
|
67
|
+
def value=(val)
|
68
|
+
if @done
|
69
|
+
raise RuntimeError.new('future value duplicated set')
|
70
|
+
end
|
71
|
+
@done = true
|
72
|
+
@queue << :done if @queue
|
73
|
+
@value = val
|
74
|
+
end
|
75
|
+
|
76
|
+
def value
|
77
|
+
loop do
|
78
|
+
if @done
|
79
|
+
return @value
|
80
|
+
elsif @error
|
81
|
+
raise @error
|
82
|
+
else
|
83
|
+
@queue.pop
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def raise_error(error)
|
89
|
+
error.set_backtrace(caller) if error.backtrace.nil?
|
90
|
+
@error = error
|
91
|
+
@queue << :error if @queue
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
class Error < StandardError
|
96
|
+
end
|
97
|
+
|
98
|
+
# stop actor
|
99
|
+
class StopError < Error
|
100
|
+
end
|
101
|
+
|
102
|
+
class StateError < Error
|
103
|
+
end
|
104
|
+
|
105
|
+
class << self
|
106
|
+
attr_accessor :default_executor
|
107
|
+
end
|
108
|
+
|
109
|
+
attr_accessor :executor
|
110
|
+
|
111
|
+
def initialize(executor: Actor.default_executor)
|
112
|
+
@inbox = Queue.new
|
113
|
+
@executor = executor
|
114
|
+
@future = Future.new
|
115
|
+
@running = false
|
116
|
+
end
|
117
|
+
|
118
|
+
# async call
|
119
|
+
def enqueue(method, *args)
|
120
|
+
self << [method, *args]
|
121
|
+
end
|
122
|
+
|
123
|
+
def <<(args)
|
124
|
+
@inbox << args
|
125
|
+
end
|
126
|
+
|
127
|
+
# sync call, push msg to inbox, and return future
|
128
|
+
#
|
129
|
+
# Example:
|
130
|
+
# future = actor.call(:result) # future
|
131
|
+
# future.value # blocking and wait for result
|
132
|
+
#
|
133
|
+
def call(method, *args)
|
134
|
+
future = Future.new
|
135
|
+
self << [future, method, *args]
|
136
|
+
future
|
137
|
+
end
|
138
|
+
|
139
|
+
# start actor
|
140
|
+
def start
|
141
|
+
raise Error.new("must set executor before start") unless executor
|
142
|
+
|
143
|
+
@running = true
|
144
|
+
executor.post do
|
145
|
+
start_loop
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
# send stop to actor
|
150
|
+
#
|
151
|
+
# Example:
|
152
|
+
# actor.send_stop
|
153
|
+
# # wait for actor actually stopped
|
154
|
+
# actor.wait
|
155
|
+
#
|
156
|
+
def send_stop
|
157
|
+
self << [:raise_error, StopError.new]
|
158
|
+
end
|
159
|
+
|
160
|
+
# wait until an error occurs
|
161
|
+
def wait
|
162
|
+
raise StateError.new('actor not running!') unless @running
|
163
|
+
@future.value
|
164
|
+
end
|
165
|
+
|
166
|
+
# start loop
|
167
|
+
def start_loop
|
168
|
+
loop_callback do |wait_message: true|
|
169
|
+
# check inbox
|
170
|
+
next Thread.pass if @inbox.empty? && !wait_message
|
171
|
+
msg = @inbox.pop
|
172
|
+
|
173
|
+
# extract sync or async call
|
174
|
+
future = nil
|
175
|
+
method, *args = msg
|
176
|
+
if method.is_a?(Future)
|
177
|
+
future = method
|
178
|
+
method, *args = args
|
179
|
+
end
|
180
|
+
begin
|
181
|
+
val = send(method, *args)
|
182
|
+
rescue StandardError => e
|
183
|
+
future.raise_error(e) if future
|
184
|
+
raise
|
185
|
+
end
|
186
|
+
# if future not nil, set value
|
187
|
+
future.value = val if future
|
188
|
+
end until @inbox.closed?
|
189
|
+
|
190
|
+
rescue StopError
|
191
|
+
# actor stop
|
192
|
+
@future.value = nil
|
193
|
+
rescue StandardError => e
|
194
|
+
@future.raise_error e
|
195
|
+
LOGGER.error("Actor #{self}") {"#{e}\n#{e.backtrace.join("\n")}"}
|
196
|
+
ensure
|
197
|
+
@running = false
|
198
|
+
@inbox.close
|
199
|
+
end
|
200
|
+
|
201
|
+
# allow inject callback into actor loop
|
202
|
+
# Example:
|
203
|
+
#
|
204
|
+
# class A
|
205
|
+
# include Actor
|
206
|
+
#
|
207
|
+
# def loop_callback
|
208
|
+
# # before handle msg
|
209
|
+
# yield
|
210
|
+
# # after handle msg
|
211
|
+
# end
|
212
|
+
# end
|
213
|
+
#
|
214
|
+
def loop_callback
|
215
|
+
yield
|
216
|
+
end
|
217
|
+
|
218
|
+
def raise_error(e)
|
219
|
+
raise e
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|