Java doc sample for consistent hashing router, see #944
* Allow return null as undefined ConsistentHashMapping
This commit is contained in:
parent
d59612609f
commit
48a0fda991
6 changed files with 159 additions and 11 deletions
|
|
@ -83,6 +83,9 @@ object ConsistentHashingRouter {
|
|||
* Note that it's not the hash that is to be returned, but the data to be
|
||||
* hashed.
|
||||
*
|
||||
* May return `null` to indicate that the message is not handled by
|
||||
* this mapping.
|
||||
*
|
||||
* If returning an `Array[Byte]` or String it will be used as is,
|
||||
* otherwise the configured [[akka.akka.serialization.Serializer]]
|
||||
* will be applied to the returned data.
|
||||
|
|
@ -99,9 +102,9 @@ object ConsistentHashingRouter {
|
|||
*
|
||||
* 1. You can define `consistentHashRoute` / `withConsistentHashMapping`
|
||||
* of the router to map incoming messages to their consistent hash key.
|
||||
* This makes the makes the decision transparent for the sender.
|
||||
* This makes the decision transparent for the sender.
|
||||
*
|
||||
* 2. The messages may implement [[akka.routing.ConsistentHashable]].
|
||||
* 2. The messages may implement [[akka.routing.ConsistentHashingRouter.ConsistentHashable]].
|
||||
* The key is part of the message and it's convenient to define it together
|
||||
* with the message definition.
|
||||
*
|
||||
|
|
@ -183,11 +186,12 @@ case class ConsistentHashingRouter(
|
|||
def withVirtualNodesFactor(vnodes: Int): ConsistentHashingRouter = copy(virtualNodesFactor = vnodes)
|
||||
|
||||
/**
|
||||
* Java API for setting the mapping from message to the data to use for the consistent hash key
|
||||
* Java API for setting the mapping from message to the data to use for the consistent hash key.
|
||||
*/
|
||||
def withConsistentHashMapping(mapping: ConsistentHashingRouter.ConsistentHashMapping) = {
|
||||
copy(consistentHashRoute = {
|
||||
case message ⇒ mapping.consistentHashKey(message)
|
||||
case message if (mapping.consistentHashKey(message).asInstanceOf[AnyRef] ne null) ⇒
|
||||
mapping.consistentHashKey(message)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -199,7 +203,7 @@ case class ConsistentHashingRouter(
|
|||
* that can't be defined in configuration.
|
||||
*/
|
||||
override def withFallback(other: RouterConfig): RouterConfig = other match {
|
||||
case fromConfig: FromConfig ⇒ this
|
||||
case _: FromConfig ⇒ this
|
||||
case otherRouter: ConsistentHashingRouter ⇒
|
||||
val useResizer =
|
||||
if (this.resizer.isEmpty && otherRouter.resizer.isDefined) otherRouter.resizer
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package docs.jrouting;
|
||||
|
||||
import org.scalatest.junit.JUnitSuite
|
||||
|
||||
class ConsistentHashingRouterDocTest extends ConsistentHashingRouterDocTestBase with JUnitSuite
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
|
||||
*/
|
||||
package docs.jrouting;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import akka.testkit.JavaTestKit;
|
||||
import akka.actor.ActorSystem;
|
||||
|
||||
//#imports1
|
||||
import akka.actor.UntypedActor;
|
||||
import akka.routing.ConsistentHashingRouter.ConsistentHashable;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.io.Serializable;
|
||||
//#imports1
|
||||
|
||||
//#imports2
|
||||
import akka.actor.Props;
|
||||
import akka.actor.ActorRef;
|
||||
import akka.routing.ConsistentHashingRouter;
|
||||
import akka.routing.ConsistentHashingRouter.ConsistentHashMapping;
|
||||
import akka.routing.ConsistentHashingRouter.ConsistentHashableEnvelope;
|
||||
//#imports2
|
||||
|
||||
public class ConsistentHashingRouterDocTestBase {
|
||||
|
||||
static ActorSystem system;
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() {
|
||||
system = ActorSystem.create();
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void teardown() {
|
||||
system.shutdown();
|
||||
}
|
||||
|
||||
//#cache-actor
|
||||
|
||||
public static class Cache extends UntypedActor {
|
||||
Map<String, String> cache = new HashMap<String, String>();
|
||||
|
||||
public void onReceive(Object msg) {
|
||||
if (msg instanceof Entry) {
|
||||
Entry entry = (Entry) msg;
|
||||
cache.put(entry.key, entry.value);
|
||||
} else if (msg instanceof Get) {
|
||||
Get get = (Get) msg;
|
||||
Object value = cache.get(get.key);
|
||||
getSender().tell(value == null ? NOT_FOUND : value,
|
||||
getContext().self());
|
||||
} else if (msg instanceof Evict) {
|
||||
Evict evict = (Evict) msg;
|
||||
cache.remove(evict.key);
|
||||
} else {
|
||||
unhandled(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Evict implements Serializable {
|
||||
public final String key;
|
||||
public Evict(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Get implements Serializable, ConsistentHashable {
|
||||
public final String key;
|
||||
public Get(String key) {
|
||||
this.key = key;
|
||||
}
|
||||
public Object consistentHashKey() {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Entry implements Serializable {
|
||||
public final String key;
|
||||
public final String value;
|
||||
public Entry(String key, String value) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static final String NOT_FOUND = "NOT_FOUND";
|
||||
//#cache-actor
|
||||
|
||||
|
||||
@Test
|
||||
public void demonstrateUsageOfConsistentHashableRouter() {
|
||||
|
||||
new JavaTestKit(system) {{
|
||||
|
||||
//#consistent-hashing-router
|
||||
|
||||
final ConsistentHashMapping consistentHashMapping = new ConsistentHashMapping() {
|
||||
@Override
|
||||
public Object consistentHashKey(Object message) {
|
||||
if (message instanceof Evict) {
|
||||
return ((Evict) message).key;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
ActorRef cache = system.actorOf(new Props(Cache.class).withRouter(
|
||||
new ConsistentHashingRouter(10).withConsistentHashMapping(consistentHashMapping)),
|
||||
"cache");
|
||||
|
||||
cache.tell(new ConsistentHashableEnvelope(
|
||||
new Entry("hello", "HELLO"), "hello"), getRef());
|
||||
cache.tell(new ConsistentHashableEnvelope(
|
||||
new Entry("hi", "HI"), "hi"), getRef());
|
||||
|
||||
cache.tell(new Get("hello"), getRef());
|
||||
expectMsgEquals("HELLO");
|
||||
|
||||
cache.tell(new Get("hi"), getRef());
|
||||
expectMsgEquals("HI");
|
||||
|
||||
cache.tell(new Evict("hi"), getRef());
|
||||
cache.tell(new Get("hi"), getRef());
|
||||
expectMsgEquals(NOT_FOUND);
|
||||
|
||||
//#consistent-hashing-router
|
||||
}};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -287,10 +287,10 @@ insight into how consistent hashing is implemented.
|
|||
There is 3 ways to define what data to use for the consistent hash key.
|
||||
|
||||
* You can define ``withConsistentHashMapping`` of the router to map incoming
|
||||
messages to their consistent hash key. This makes the makes the decision
|
||||
messages to their consistent hash key. This makes the the decision
|
||||
transparent for the sender.
|
||||
|
||||
* The messages may implement ``akka.routing.ConsistentHashable``.
|
||||
* The messages may implement ``akka.routing.ConsistentHashingRouter.ConsistentHashable``.
|
||||
The key is part of the message and it's convenient to define it together
|
||||
with the message definition.
|
||||
|
||||
|
|
@ -303,7 +303,11 @@ the same time for one router. The ``withConsistentHashMapping`` is tried first.
|
|||
|
||||
Code example:
|
||||
|
||||
FIXME Java example of consistent routing
|
||||
.. includecode:: code/docs/jrouting/ConsistentHashingRouterDocTestBase.java
|
||||
:include: imports1,cache-actor
|
||||
|
||||
.. includecode:: code/docs/jrouting/ConsistentHashingRouterDocTestBase.java
|
||||
:include: imports2,consistent-hashing-router
|
||||
|
||||
In the above example you see that the ``Get`` message implements ``ConsistentHashable`` itself,
|
||||
while the ``Entry`` message is wrapped in a ``ConsistentHashableEnvelope``. The ``Evict``
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ object ConsistentHashingRouterDocSpec {
|
|||
//#cache-actor
|
||||
import akka.actor.Actor
|
||||
import akka.routing.ConsistentHashingRouter.ConsistentHashable
|
||||
import akka.routing.ConsistentHashingRouter.ConsistentHashableEnvelope
|
||||
|
||||
class Cache extends Actor {
|
||||
var cache = Map.empty[String, String]
|
||||
|
|
|
|||
|
|
@ -292,10 +292,10 @@ insight into how consistent hashing is implemented.
|
|||
There is 3 ways to define what data to use for the consistent hash key.
|
||||
|
||||
* You can define ``consistentHashRoute`` of the router to map incoming
|
||||
messages to their consistent hash key. This makes the makes the decision
|
||||
messages to their consistent hash key. This makes the decision
|
||||
transparent for the sender.
|
||||
|
||||
* The messages may implement ``akka.routing.ConsistentHashable``.
|
||||
* The messages may implement ``akka.routing.ConsistentHashingRouter.ConsistentHashable``.
|
||||
The key is part of the message and it's convenient to define it together
|
||||
with the message definition.
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue