mikka 1.1.1-java → 2.0.0.pre0-java
Sign up to get free protection for your applications and to get access to all the features.
- data/.rvmrc +1 -1
- data/Gemfile +4 -0
- data/README.mdown +6 -3
- data/lib/akka.rb +12 -19
- data/lib/mikka.rb +64 -134
- data/lib/mikka/version.rb +1 -1
- data/mikka.gemspec +3 -4
- data/spec/mikka_spec.rb +49 -0
- data/spec/spec_helper.rb +3 -0
- metadata +13 -27
- data/examples/hello_world.rb +0 -107
- data/examples/load_balancing1.rb +0 -20
- data/examples/load_balancing2.rb +0 -23
- data/examples/proc_example.rb +0 -24
- data/examples/remoting.rb +0 -70
- data/examples/simple_example.rb +0 -16
- data/examples/supervision1.rb +0 -55
data/.rvmrc
CHANGED
@@ -1 +1 @@
|
|
1
|
-
rvm --create use jruby-1.6.
|
1
|
+
rvm --create use jruby-1.6.7@mikka
|
data/Gemfile
CHANGED
data/README.mdown
CHANGED
@@ -2,6 +2,8 @@
|
|
2
2
|
|
3
3
|
Mikka is a thin Ruby wrapper around Akka. It makes Akka's Java API more pleasing to the Rubyist's eye.
|
4
4
|
|
5
|
+
It uses Akka 1.2, but there are plans to create an Akka 2.0 version as soon as possible. Follow the 2.0 development in the [`mikka-2.0` branch](https://github.com/iconara/mikka/tree/mikka-2.0).
|
6
|
+
|
5
7
|
## Work in progress
|
6
8
|
|
7
9
|
Mikka is a work in progress, but currently used in production. It currently mostly scratches my own itchs, but improvement suggestions and patches are welcome.
|
@@ -12,9 +14,9 @@ If you make something that can serve as a useful illustration of some concept, p
|
|
12
14
|
|
13
15
|
## Requirements
|
14
16
|
|
15
|
-
|
17
|
+
Tested in JRuby 1.6.5+ and Ruby 1.9 mode (run with `jruby --1.9` or set `JRUBY_OPTS='--1.9`).
|
16
18
|
|
17
|
-
The required Akka and Scala JARs are loaded from the [akka-actor-jars](https://rubygems.org/gems/akka-actor-jars) and [scala-library-jars](https://rubygems.org/gems/scala-library-jars) wrapper gems.
|
19
|
+
The required Akka and Scala JARs are loaded from the [akka-actor-jars](https://rubygems.org/gems/akka-actor-jars), [akka-remote-jars](https://rubygems.org/gems/akka-remote-jars) and [scala-library-jars](https://rubygems.org/gems/scala-library-jars) wrapper gems.
|
18
20
|
|
19
21
|
## Installation
|
20
22
|
|
@@ -23,10 +25,11 @@ The required Akka and Scala JARs are loaded from the [akka-actor-jars](https://r
|
|
23
25
|
## Contributors
|
24
26
|
|
25
27
|
Theo Hultberg, [@iconara](http://twitter.com/iconara)
|
28
|
+
Daniel Gaiottino, [@bantai](http://twitter.com/bantai)
|
26
29
|
|
27
30
|
## License
|
28
31
|
|
29
|
-
Mikka is licensed under the Apache 2 license, the same as Akka. See http://akka.io/docs/akka/1.
|
32
|
+
Mikka is licensed under the Apache 2 license, the same as Akka. See http://akka.io/docs/akka/1.2/project/licenses.html
|
30
33
|
|
31
34
|
## Mikka?
|
32
35
|
|
data/lib/akka.rb
CHANGED
@@ -2,30 +2,23 @@
|
|
2
2
|
|
3
3
|
require 'java'
|
4
4
|
require 'akka-actor-jars'
|
5
|
-
require 'akka-remote-jars'
|
6
5
|
|
7
6
|
|
8
7
|
module Akka
|
9
|
-
import 'akka.actor.Actors'
|
10
|
-
|
11
8
|
module Actor
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
class UntypedActor
|
18
|
-
def self.create(*args)
|
19
|
-
new(*args)
|
20
|
-
end
|
21
|
-
end
|
9
|
+
java_import 'akka.actor.ActorSystem'
|
10
|
+
java_import 'akka.actor.ActorRef'
|
11
|
+
java_import 'akka.actor.UntypedActor'
|
12
|
+
java_import 'akka.actor.Props'
|
13
|
+
java_import 'akka.actor.Terminated'
|
22
14
|
end
|
23
|
-
|
24
|
-
module
|
25
|
-
|
15
|
+
|
16
|
+
module Dispatch
|
17
|
+
java_import 'akka.dispatch.Await'
|
26
18
|
end
|
27
|
-
|
28
|
-
module
|
29
|
-
|
19
|
+
|
20
|
+
module Util
|
21
|
+
java_import 'akka.util.Duration'
|
22
|
+
java_import 'akka.util.Timeout'
|
30
23
|
end
|
31
24
|
end
|
data/lib/mikka.rb
CHANGED
@@ -1,192 +1,122 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
-
require 'java'
|
4
3
|
require 'akka'
|
5
4
|
|
6
5
|
|
7
6
|
module Mikka
|
8
|
-
|
9
|
-
|
10
|
-
def self.actor_of(*args, &block)
|
11
|
-
Akka::Actor::Actors.actor_of(*args, &block)
|
7
|
+
def self.create_actor_system(*args)
|
8
|
+
Akka::Actor::ActorSystem.create(*args)
|
12
9
|
end
|
13
|
-
|
14
|
-
def self.
|
15
|
-
Akka::
|
10
|
+
|
11
|
+
def self.await_result(future, options={})
|
12
|
+
Akka::Dispatch::Await.result(future, Duration[options[:timeout]])
|
16
13
|
end
|
17
14
|
|
18
|
-
def self.
|
19
|
-
|
15
|
+
def self.current_actor=(actor)
|
16
|
+
Thread.current[:mikka_current_actor] = actor
|
20
17
|
end
|
21
18
|
|
22
19
|
def self.current_actor
|
23
20
|
Thread.current[:mikka_current_actor]
|
24
21
|
end
|
25
22
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
def self.poison_pill
|
32
|
-
Akka::Actor::Actors.poison_pill
|
33
|
-
end
|
23
|
+
def self.capture_current_actor(ref)
|
24
|
+
self.current_actor = ref
|
25
|
+
yield
|
26
|
+
ensure
|
27
|
+
self.current_actor = nil
|
34
28
|
end
|
35
29
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
30
|
+
ActorRef = Akka::Actor::ActorRef
|
31
|
+
Props = Akka::Actor::Props
|
32
|
+
Duration = Akka::Util::Duration
|
33
|
+
Timeout = Akka::Util::Timeout
|
34
|
+
Terminated = Akka::Actor::Terminated
|
35
|
+
|
36
|
+
class Props
|
37
|
+
def self.[](*args, &block)
|
38
|
+
options = args.last.is_a?(Hash) && args.pop
|
39
|
+
creator = ((args.first.is_a?(Proc) || args.first.is_a?(Class)) && args.first) || (options && options[:creator]) || block
|
40
|
+
raise ArgumentError, %(No creator specified) unless creator
|
41
|
+
props = new
|
42
|
+
props = props.with_creator(creator)
|
43
|
+
props
|
45
44
|
end
|
46
|
-
|
47
|
-
|
48
|
-
|
45
|
+
|
46
|
+
class << self
|
47
|
+
alias_method :create, :[]
|
49
48
|
end
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
49
|
+
end
|
50
|
+
|
51
|
+
class Duration
|
52
|
+
def self.[](*args)
|
53
|
+
Akka::Util::Duration.apply(*args)
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
|
+
class ActorRef
|
58
|
+
def <<(msg)
|
59
|
+
tell(msg, Mikka.current_actor)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
57
63
|
module RubyesqueActorCallbacks
|
58
64
|
def receive(message); end
|
59
65
|
def pre_start; end
|
60
66
|
def post_stop; end
|
61
67
|
def pre_restart(reason); end
|
62
68
|
def post_restart(reason); end
|
63
|
-
|
69
|
+
|
64
70
|
def onReceive(message); receive(message); end
|
65
71
|
def preStart; super; pre_start; end
|
66
72
|
def postStop; super; post_stop; end
|
67
73
|
def preRestart(reason); super; pre_restart(reason); end
|
68
74
|
def postRestart(reason); super; post_restart(reason); end
|
69
75
|
end
|
70
|
-
|
76
|
+
|
71
77
|
module ImplicitSender
|
72
78
|
def onReceive(*args)
|
73
|
-
capture_current_actor { super }
|
79
|
+
Mikka.capture_current_actor(get_self) { super }
|
74
80
|
end
|
75
81
|
|
76
82
|
def preStart(*args)
|
77
|
-
capture_current_actor { super }
|
83
|
+
Mikka.capture_current_actor(get_self) { super }
|
78
84
|
end
|
79
85
|
|
80
86
|
def postStop(*args)
|
81
|
-
capture_current_actor { super }
|
87
|
+
Mikka.capture_current_actor(get_self) { super }
|
82
88
|
end
|
83
89
|
|
84
90
|
def preRestart(*args)
|
85
|
-
capture_current_actor { super }
|
91
|
+
Mikka.capture_current_actor(get_self) { super }
|
86
92
|
end
|
87
93
|
|
88
94
|
def postRestart(*args)
|
89
|
-
capture_current_actor { super }
|
90
|
-
end
|
91
|
-
|
92
|
-
private
|
93
|
-
|
94
|
-
def capture_current_actor
|
95
|
-
Thread.current[:mikka_current_actor] = context
|
96
|
-
yield
|
97
|
-
ensure
|
98
|
-
Thread.current[:mikka_current_actor] = nil
|
99
|
-
end
|
95
|
+
Mikka.capture_current_actor(get_self) { super }
|
96
|
+
end
|
100
97
|
end
|
101
|
-
|
102
|
-
module SupervisionDsl
|
103
|
-
module ClassMethods
|
104
|
-
def fault_handling(config)
|
105
|
-
trap = config[:trap].map { |e| e.java_class }
|
106
|
-
max_retries = config.fetch(:max_retries, 5)
|
107
|
-
time_range = config.fetch(:time_range, 5000)
|
108
|
-
case config[:strategy]
|
109
|
-
when :all_for_one
|
110
|
-
@fault_handling_strategy = Akka::Config::Supervision::AllForOneStrategy.new(trap, max_retries, time_range)
|
111
|
-
when :one_for_one
|
112
|
-
@fault_handling_strategy = Akka::Config::Supervision::OneForOneStrategy.new(trap, max_retries, time_range)
|
113
|
-
else
|
114
|
-
raise ArgumentError, 'strategy must be one of :all_for_one or :one_for_one'
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
def registered_fault_handling_strategy
|
119
|
-
@fault_handling_strategy
|
120
|
-
end
|
121
|
-
|
122
|
-
def life_cycle(type)
|
123
|
-
@life_cycle = begin
|
124
|
-
case type
|
125
|
-
when :permanent then Akka::Config::Supervision.permanent
|
126
|
-
when :temporary then Akka::Config::Supervision.temporary
|
127
|
-
when :undefined then Akka::Config::Supervision.undefined_life_cycle
|
128
|
-
else raise ArgumentError, 'type must be one of :permanent, :temporary or :undefined'
|
129
|
-
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def registered_life_cycle
|
134
|
-
@life_cycle
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
module InstanceMethods
|
139
|
-
def initialize(*args)
|
140
|
-
super
|
141
|
-
if self.class.registered_fault_handling_strategy
|
142
|
-
context.fault_handler = self.class.registered_fault_handling_strategy
|
143
|
-
end
|
144
|
-
if self.class.registered_life_cycle
|
145
|
-
context.life_cycle = self.class.registered_life_cycle
|
146
|
-
end
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
def self.included(m)
|
151
|
-
m.extend(ClassMethods)
|
152
|
-
m.include(InstanceMethods)
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
98
|
+
|
156
99
|
class Actor < Akka::Actor::UntypedActor
|
157
|
-
include SupervisionDsl
|
158
100
|
include RubyesqueActorCallbacks
|
159
101
|
include ImplicitSender
|
102
|
+
|
103
|
+
class << self
|
104
|
+
alias_method :apply, :new
|
105
|
+
alias_method :create, :new
|
106
|
+
end
|
160
107
|
end
|
161
|
-
|
162
|
-
|
163
|
-
def
|
164
|
-
|
108
|
+
|
109
|
+
module PropsConstructor
|
110
|
+
def Props(&block)
|
111
|
+
Props.create(&block)
|
165
112
|
end
|
166
113
|
end
|
167
114
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
raise ArgumentError, "Either :actors or :type and :count must be specified" unless type && count
|
174
|
-
actors = (0...count).map { actor_of(type) }
|
175
|
-
end
|
176
|
-
actors.each { |a| a.start }
|
177
|
-
actor_list = Arrays.as_list(actors.to_java)
|
178
|
-
actor_seq = Akka::Routing::CyclicIterator.new(actor_list)
|
179
|
-
actor_factory = proc { actor_seq }.to_function
|
180
|
-
Akka::Routing::Routing.load_balancer_actor(actor_factory)
|
115
|
+
module Useful
|
116
|
+
include PropsConstructor
|
117
|
+
extend PropsConstructor
|
118
|
+
|
119
|
+
Props = ::Mikka::Props
|
181
120
|
end
|
182
121
|
end
|
183
122
|
|
184
|
-
module Akka
|
185
|
-
module Actor
|
186
|
-
module ActorRef
|
187
|
-
def <<(message)
|
188
|
-
send_one_way(message, Mikka.current_actor)
|
189
|
-
end
|
190
|
-
end
|
191
|
-
end
|
192
|
-
end
|
data/lib/mikka/version.rb
CHANGED
data/mikka.gemspec
CHANGED
@@ -9,16 +9,15 @@ Gem::Specification.new do |s|
|
|
9
9
|
s.name = 'mikka'
|
10
10
|
s.version = Mikka::VERSION
|
11
11
|
s.platform = 'java'
|
12
|
-
s.authors = ['Theo Hultberg']
|
13
|
-
s.email = ['theo@iconara.net']
|
12
|
+
s.authors = ['Theo Hultberg', 'Daniel Gaiottino']
|
13
|
+
s.email = ['theo@iconara.net', 'daniel.gaiottino@gmail.com']
|
14
14
|
s.homepage = 'http://github.com/iconara/mikka'
|
15
15
|
s.summary = %q{Mikka is a JRuby wrapper for Akka}
|
16
16
|
s.description = %q{Mikka adapts Akka's Java API to fit better with Ruby}
|
17
17
|
|
18
18
|
s.rubyforge_project = 'mikka'
|
19
19
|
|
20
|
-
s.add_dependency 'akka-actor-jars', '~>
|
21
|
-
s.add_dependency 'akka-remote-jars', '~> 1.2.0'
|
20
|
+
s.add_dependency 'akka-actor-jars', '~> 2.0.2'
|
22
21
|
|
23
22
|
s.files = `git ls-files`.split("\n")
|
24
23
|
# s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/spec/mikka_spec.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
module Mikka
|
5
|
+
class TestActor < Mikka::Actor
|
6
|
+
def receive(msg)
|
7
|
+
sender << msg
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'actor creation' do
|
12
|
+
before do
|
13
|
+
@system = Mikka.create_actor_system('testsystem')
|
14
|
+
end
|
15
|
+
|
16
|
+
after do
|
17
|
+
@system.shutdown
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'creates an actor from a class' do
|
21
|
+
actor_props = Props[TestActor]
|
22
|
+
actor = @system.actor_of(actor_props, 'some_actor')
|
23
|
+
actor.should be_a(ActorRef)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'creates an actor from a factory proc' do
|
27
|
+
actor_props = Props[:creator => proc { TestActor.new }]
|
28
|
+
actor = @system.actor_of(actor_props, 'some_actor')
|
29
|
+
actor.should be_a(ActorRef)
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'creates an actor from a factory block' do
|
33
|
+
actor_props = Props.create { TestActor.new }
|
34
|
+
actor = @system.actor_of(actor_props, 'some_actor')
|
35
|
+
actor.should be_a(ActorRef)
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'creates an actor from a factory block passed to the Props function' do
|
39
|
+
actor_props = Useful.Props { TestActor.new }
|
40
|
+
actor = @system.actor_of(actor_props, 'some_actor')
|
41
|
+
actor.should be_a(ActorRef)
|
42
|
+
end
|
43
|
+
|
44
|
+
# future = actor.ask(:hi, 1000)
|
45
|
+
# reply = Mikka.await_result(future, :timeout => '1000ms')
|
46
|
+
# reply.should == :hi
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
CHANGED
@@ -1,41 +1,32 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mikka
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
version:
|
4
|
+
prerelease: 6
|
5
|
+
version: 2.0.0.pre0
|
6
6
|
platform: java
|
7
7
|
authors:
|
8
8
|
- Theo Hultberg
|
9
|
+
- Daniel Gaiottino
|
9
10
|
autorequire:
|
10
11
|
bindir: bin
|
11
12
|
cert_chain: []
|
12
|
-
date:
|
13
|
+
date: 2012-08-07 00:00:00.000000000Z
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: akka-actor-jars
|
16
|
-
version_requirements: &
|
17
|
+
version_requirements: &2058 !ruby/object:Gem::Requirement
|
17
18
|
requirements:
|
18
19
|
- - ~>
|
19
20
|
- !ruby/object:Gem::Version
|
20
|
-
version:
|
21
|
+
version: 2.0.2
|
21
22
|
none: false
|
22
|
-
requirement: *
|
23
|
-
prerelease: false
|
24
|
-
type: :runtime
|
25
|
-
- !ruby/object:Gem::Dependency
|
26
|
-
name: akka-remote-jars
|
27
|
-
version_requirements: &2074 !ruby/object:Gem::Requirement
|
28
|
-
requirements:
|
29
|
-
- - ~>
|
30
|
-
- !ruby/object:Gem::Version
|
31
|
-
version: 1.2.0
|
32
|
-
none: false
|
33
|
-
requirement: *2074
|
23
|
+
requirement: *2058
|
34
24
|
prerelease: false
|
35
25
|
type: :runtime
|
36
26
|
description: Mikka adapts Akka's Java API to fit better with Ruby
|
37
27
|
email:
|
38
28
|
- theo@iconara.net
|
29
|
+
- daniel.gaiottino@gmail.com
|
39
30
|
executables: []
|
40
31
|
extensions: []
|
41
32
|
extra_rdoc_files: []
|
@@ -45,17 +36,12 @@ files:
|
|
45
36
|
- Gemfile
|
46
37
|
- README.mdown
|
47
38
|
- Rakefile
|
48
|
-
- examples/hello_world.rb
|
49
|
-
- examples/load_balancing1.rb
|
50
|
-
- examples/load_balancing2.rb
|
51
|
-
- examples/proc_example.rb
|
52
|
-
- examples/remoting.rb
|
53
|
-
- examples/simple_example.rb
|
54
|
-
- examples/supervision1.rb
|
55
39
|
- lib/akka.rb
|
56
40
|
- lib/mikka.rb
|
57
41
|
- lib/mikka/version.rb
|
58
42
|
- mikka.gemspec
|
43
|
+
- spec/mikka_spec.rb
|
44
|
+
- spec/spec_helper.rb
|
59
45
|
homepage: http://github.com/iconara/mikka
|
60
46
|
licenses: []
|
61
47
|
post_install_message:
|
@@ -70,13 +56,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
70
56
|
none: false
|
71
57
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
72
58
|
requirements:
|
73
|
-
- - ! '
|
59
|
+
- - ! '>'
|
74
60
|
- !ruby/object:Gem::Version
|
75
|
-
version:
|
61
|
+
version: 1.3.1
|
76
62
|
none: false
|
77
63
|
requirements: []
|
78
64
|
rubyforge_project: mikka
|
79
|
-
rubygems_version: 1.8.
|
65
|
+
rubygems_version: 1.8.15
|
80
66
|
signing_key:
|
81
67
|
specification_version: 3
|
82
68
|
summary: Mikka is a JRuby wrapper for Akka
|
data/examples/hello_world.rb
DELETED
@@ -1,107 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$: << File.expand_path('../../lib', __FILE__)
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'mikka'
|
7
|
-
|
8
|
-
# 0.
|
9
|
-
# The numbers at the top of the comment blocks follow the flow of the
|
10
|
-
# application, read them in order to see the sequence of events.
|
11
|
-
|
12
|
-
# 1.
|
13
|
-
# The simplest way to create an actor is to do it with a block. The block
|
14
|
-
# will receive each message and execute in the scope of an actor object (so
|
15
|
-
# `context` will be available -- more on that later).
|
16
|
-
#
|
17
|
-
# The variable `phil` will not refer directly to an actor instance, but to an
|
18
|
-
# `ActorRef`. There are many reasons for this, and for the full picture refer
|
19
|
-
# to the Akka documentation. The short explanation is that it makes it
|
20
|
-
# possible to restart and replace the actor without the clients knowing that
|
21
|
-
# the actor instance was changed, and it makes remote actors transparent.
|
22
|
-
phil = Mikka.actor do |msg|
|
23
|
-
# 8.
|
24
|
-
# Ruby doesn't have pattern matching, but `case` is usually enough. If you
|
25
|
-
# Have separate classes for your messages you can match on class.
|
26
|
-
case msg
|
27
|
-
when Introduction
|
28
|
-
# 9.
|
29
|
-
# The `Introduction` class has a field called `to_whom` that contains a
|
30
|
-
# reference to an actor that someone want to introduce us to. Let's send
|
31
|
-
# that actor a `Greeting`.
|
32
|
-
msg.to_whom << Greeting.new('Hello, dear sir.')
|
33
|
-
when Greeting
|
34
|
-
puts "Received greeting: #{msg.body}"
|
35
|
-
# 12.
|
36
|
-
# The reply got routed back to this actor. Now we want to shut down this
|
37
|
-
# actor too, so that the application can shut down.
|
38
|
-
context.exit
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
# 2.
|
43
|
-
# If you need more control over your actor's life cycle, or want to create
|
44
|
-
# more than one of the same you can can declare a subclass of Mikka::Actor.
|
45
|
-
# The #receive method is called for each message the actor receives. You can
|
46
|
-
# do things when the actor starts by implementing #pre_start, and when the
|
47
|
-
# actor stops by implementing #post_stop.
|
48
|
-
#
|
49
|
-
# Don't create instances of this class yourself, an error will be raised if
|
50
|
-
# it's done in the wrong way, see below for how it's supposed to be done.
|
51
|
-
class Replier < Mikka::Actor
|
52
|
-
def receive(msg)
|
53
|
-
case msg
|
54
|
-
when Greeting
|
55
|
-
puts "Received greeting: #{msg.body}"
|
56
|
-
# 10.
|
57
|
-
# To reply to a message without having to explicitly refer to the sender
|
58
|
-
# use #reply (you can, however, store the sender and reply later if you
|
59
|
-
# want, it is available through `context.sender.get`).
|
60
|
-
#
|
61
|
-
# A word of caution: the sender is not always set, for example when the
|
62
|
-
# message was sent from a non-actor context like in 6. Also, the Scala
|
63
|
-
# API sets the sender implicitly in a way that is not possible in Java
|
64
|
-
# or Ruby, and even if Mikka does it's best to emulate the Scala way,
|
65
|
-
# it's not foolproof. If you want to guard agains errors when replying
|
66
|
-
# you can use #reply_safe instead of #reply. It will return true if the
|
67
|
-
# message could be sent, and false otherwise.
|
68
|
-
context.reply(Greeting.new('Why, hello old chap.'))
|
69
|
-
# 11.
|
70
|
-
# Now we're through with this actor, so we shut it down.
|
71
|
-
context.exit
|
72
|
-
end
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
# 3.
|
77
|
-
# This is how you create an actor reference from a subclass of Mikka::Actor.
|
78
|
-
# Creating the instance this way makes sure that the actor is set up correctly
|
79
|
-
# (refer to the Akka documentation as to why it works this way).
|
80
|
-
sam = Mikka.actor_of(Replier)
|
81
|
-
|
82
|
-
# 4.
|
83
|
-
# Messages can be anything, but if your messages are more complex than a
|
84
|
-
# simple string or symbol you are best off declaring a proper class to
|
85
|
-
# encapsulate them. `Struct` is convenient in this case (but creates mutable
|
86
|
-
# objects, consider using the `immutable_struct` gem instead).
|
87
|
-
class Introduction < Struct.new(:to_whom); end
|
88
|
-
class Greeting < Struct.new(:body); end
|
89
|
-
|
90
|
-
# 5.
|
91
|
-
# An actor must be started before it can be used!
|
92
|
-
phil.start
|
93
|
-
sam.start
|
94
|
-
|
95
|
-
# 6.
|
96
|
-
# And finally, this is how to send a message to an actor. In Erlang and Scala
|
97
|
-
# it is done with !, but that operator is not overridable in Ruby, so we have
|
98
|
-
# to make do with <<. The Akka Java API defines #send_one_way (actually
|
99
|
-
# sendOneWay, but JRuby fixes the casing for us), which can also be used.
|
100
|
-
#
|
101
|
-
# Here we send a message to `phil`, the message is an object that contains a
|
102
|
-
# reference to the actor `sam`.
|
103
|
-
phil << Introduction.new(sam)
|
104
|
-
|
105
|
-
# 7.
|
106
|
-
# The application will keep running until the last actor is dead. If you want
|
107
|
-
# to force shutdown you can use `Mikka.registry.shutdown_all`.
|
data/examples/load_balancing1.rb
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$: << File.expand_path('../../lib', __FILE__)
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'mikka'
|
7
|
-
|
8
|
-
|
9
|
-
worker1 = Mikka.actor { |msg| puts "Worker 1 working on #{msg}" }
|
10
|
-
worker2 = Mikka.actor { |msg| puts "Worker 2 working on #{msg}" }
|
11
|
-
balancer = Mikka.load_balancer(:actors => [worker1, worker2])
|
12
|
-
|
13
|
-
10.times do |i|
|
14
|
-
balancer << "item #{i}"
|
15
|
-
end
|
16
|
-
|
17
|
-
balancer << Mikka::Messages.broadcast("a message to everyone")
|
18
|
-
balancer << Mikka::Messages.poison_pill
|
19
|
-
|
20
|
-
Mikka.registry.shutdown_all
|
data/examples/load_balancing2.rb
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$: << File.expand_path('../../lib', __FILE__)
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'mikka'
|
7
|
-
|
8
|
-
|
9
|
-
class Worker < Mikka::Actor
|
10
|
-
def receive(message)
|
11
|
-
puts "#{context.uuid} Work on #{message}"
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
balancer = Mikka.load_balancer(:type => Worker, :count => 4)
|
16
|
-
|
17
|
-
10.times do |i|
|
18
|
-
balancer << "item #{i}"
|
19
|
-
end
|
20
|
-
|
21
|
-
balancer << Mikka::Messages.broadcast("a message to everyone")
|
22
|
-
|
23
|
-
Mikka.registry.shutdown_all
|
data/examples/proc_example.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$: << File.expand_path('../../lib', __FILE__)
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'mikka'
|
7
|
-
|
8
|
-
|
9
|
-
actor = Mikka.actor do |message|
|
10
|
-
case message
|
11
|
-
when 'hi'
|
12
|
-
puts "hello yourself"
|
13
|
-
when 'goodbye'
|
14
|
-
puts "adieu"
|
15
|
-
context.exit
|
16
|
-
else
|
17
|
-
puts "sorry, come again?"
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
actor.start
|
22
|
-
actor << 'hi'
|
23
|
-
actor << 'hello'
|
24
|
-
actor << 'goodbye'
|
data/examples/remoting.rb
DELETED
@@ -1,70 +0,0 @@
|
|
1
|
-
$: << File.expand_path('../../lib', __FILE__)
|
2
|
-
|
3
|
-
# Run this with the argument 'server' to start a server, then run again
|
4
|
-
# without argument to run a client
|
5
|
-
|
6
|
-
require 'mikka'
|
7
|
-
|
8
|
-
|
9
|
-
SERVICE_NAME = 'translation-service'
|
10
|
-
SERVER_PORT = 1337
|
11
|
-
|
12
|
-
|
13
|
-
if ARGV.any? && ARGV.first == 'server'
|
14
|
-
# this is the server, it spawns the actor, starts a server and registers the
|
15
|
-
# actor with the server
|
16
|
-
|
17
|
-
class ServerActor < Mikka::Actor
|
18
|
-
TRANSLATIONS = {
|
19
|
-
'bonjour' => 'hello'
|
20
|
-
}
|
21
|
-
|
22
|
-
def receive(message)
|
23
|
-
context.reply_safe(TRANSLATIONS[message])
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
# start the server, the host can be specified with :host and defaults to
|
28
|
-
# localhost (the port defaults to 2552, but 1337 is cooler)
|
29
|
-
server = Mikka::Remote.start(:port => SERVER_PORT)
|
30
|
-
|
31
|
-
# create and register an actor with the server, this ID is used by the
|
32
|
-
# client to get a reference to the actor
|
33
|
-
server.register(SERVICE_NAME, Mikka.actor_of(ServerActor))
|
34
|
-
|
35
|
-
# now we're just waiting for messages
|
36
|
-
else
|
37
|
-
# this is the client code, it connects to the remote actor and sends it a message
|
38
|
-
|
39
|
-
class ClientActor < Mikka::Actor
|
40
|
-
def initialize(word)
|
41
|
-
super() # remember to use super with parentheses!
|
42
|
-
@word = word
|
43
|
-
end
|
44
|
-
|
45
|
-
def pre_start
|
46
|
-
# this gets an actor reference to the remote actor, you need to supply
|
47
|
-
# the ID the actor was registered with, and the host and port where it's
|
48
|
-
# running (these default to localhost and 2552)
|
49
|
-
@translation_actor = Mikka::Remote.actor_for(SERVICE_NAME, :port => SERVER_PORT)
|
50
|
-
@translation_actor << @word
|
51
|
-
end
|
52
|
-
|
53
|
-
def receive(message)
|
54
|
-
if message
|
55
|
-
puts "#{@word} means #{message}"
|
56
|
-
else
|
57
|
-
puts "#{@word} has no meaning"
|
58
|
-
end
|
59
|
-
context.exit
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
# if you want to receive replies you need to start a server on the client
|
64
|
-
# side too, but you can use the no-args constructor to use the defaults
|
65
|
-
# (just don't use the defaults for both server and client)
|
66
|
-
Mikka::Remote.start
|
67
|
-
|
68
|
-
client = Mikka.actor_of { ClientActor.new('bonjour') }
|
69
|
-
client.start
|
70
|
-
end
|
data/examples/simple_example.rb
DELETED
@@ -1,16 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$: << File.expand_path('../../lib', __FILE__)
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'mikka'
|
7
|
-
|
8
|
-
|
9
|
-
class Stallone < Mikka::Actor
|
10
|
-
def receive(message)
|
11
|
-
context.exit if message == 'punch!'
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
stallone = Mikka.actor_of(Stallone).start
|
16
|
-
stallone << 'punch!'
|
data/examples/supervision1.rb
DELETED
@@ -1,55 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
$: << File.expand_path('../../lib', __FILE__)
|
4
|
-
|
5
|
-
require 'bundler/setup'
|
6
|
-
require 'mikka'
|
7
|
-
|
8
|
-
|
9
|
-
class Worker < Mikka::Actor
|
10
|
-
life_cycle :permanent
|
11
|
-
|
12
|
-
def pre_start
|
13
|
-
puts "#{context.id} starting"
|
14
|
-
end
|
15
|
-
|
16
|
-
def pre_restart(reason)
|
17
|
-
puts "#{context.id} restarting"
|
18
|
-
end
|
19
|
-
|
20
|
-
def post_restart(reason)
|
21
|
-
puts "#{context.id} restarted"
|
22
|
-
end
|
23
|
-
|
24
|
-
def post_stop
|
25
|
-
puts "#{context.id} stopped"
|
26
|
-
end
|
27
|
-
|
28
|
-
def receive(message)
|
29
|
-
raise java.lang.Exception.new('Oh, shucks') if message == 'hard work'
|
30
|
-
puts "#{context.id} Work on #{message}"
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class Manager < Mikka::Actor
|
35
|
-
fault_handling :strategy => :all_for_one, :trap => [java.lang.Exception], :max_retries => 3, :time_range => 3000
|
36
|
-
|
37
|
-
def pre_start
|
38
|
-
@worker1 = Mikka.actor_of { Worker.new }
|
39
|
-
@worker2 = Mikka.actor_of { Worker.new }
|
40
|
-
@worker1.id = 'worker1'
|
41
|
-
@worker2.id = 'worker2'
|
42
|
-
context.start_link(@worker1)
|
43
|
-
context.start_link(@worker2)
|
44
|
-
@worker1 << 'simple work'
|
45
|
-
@worker2 << 'hard work'
|
46
|
-
@worker2 << 'simple work'
|
47
|
-
@worker2 << 'simple work'
|
48
|
-
@worker2 << 'hard work'
|
49
|
-
@worker2 << 'simple work'
|
50
|
-
@worker2 << 'simple work'
|
51
|
-
@worker2 << 'simple work'
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
manager = Mikka.actor_of(Manager).start
|