ciri 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/ciri-ethereum/ciri.svg?branch=master)](https://travis-ci.org/ciri-ethereum/ciri)
|
4
|
+
[![Gitter](https://badges.gitter.im/join.svg)](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
|