Java doc sample for consistent hashing router, see #944

* Allow return null as undefined ConsistentHashMapping
This commit is contained in:
Patrik Nordwall 2012-09-17 11:40:06 +02:00
parent d59612609f
commit 48a0fda991
6 changed files with 159 additions and 11 deletions

View file

@ -83,6 +83,9 @@ object ConsistentHashingRouter {
* Note that it's not the hash that is to be returned, but the data to be * Note that it's not the hash that is to be returned, but the data to be
* hashed. * 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, * If returning an `Array[Byte]` or String it will be used as is,
* otherwise the configured [[akka.akka.serialization.Serializer]] * otherwise the configured [[akka.akka.serialization.Serializer]]
* will be applied to the returned data. * will be applied to the returned data.
@ -99,9 +102,9 @@ object ConsistentHashingRouter {
* *
* 1. You can define `consistentHashRoute` / `withConsistentHashMapping` * 1. You can define `consistentHashRoute` / `withConsistentHashMapping`
* of the router to map incoming messages to their consistent hash key. * 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 * The key is part of the message and it's convenient to define it together
* with the message definition. * with the message definition.
* *
@ -183,11 +186,12 @@ case class ConsistentHashingRouter(
def withVirtualNodesFactor(vnodes: Int): ConsistentHashingRouter = copy(virtualNodesFactor = vnodes) 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) = { def withConsistentHashMapping(mapping: ConsistentHashingRouter.ConsistentHashMapping) = {
copy(consistentHashRoute = { 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. * that can't be defined in configuration.
*/ */
override def withFallback(other: RouterConfig): RouterConfig = other match { override def withFallback(other: RouterConfig): RouterConfig = other match {
case fromConfig: FromConfig this case _: FromConfig this
case otherRouter: ConsistentHashingRouter case otherRouter: ConsistentHashingRouter
val useResizer = val useResizer =
if (this.resizer.isEmpty && otherRouter.resizer.isDefined) otherRouter.resizer if (this.resizer.isEmpty && otherRouter.resizer.isDefined) otherRouter.resizer

View file

@ -0,0 +1,5 @@
package docs.jrouting;
import org.scalatest.junit.JUnitSuite
class ConsistentHashingRouterDocTest extends ConsistentHashingRouterDocTestBase with JUnitSuite

View file

@ -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
}};
}
}

View file

@ -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. 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 * 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. 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 The key is part of the message and it's convenient to define it together
with the message definition. with the message definition.
@ -303,7 +303,11 @@ the same time for one router. The ``withConsistentHashMapping`` is tried first.
Code example: 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, In the above example you see that the ``Get`` message implements ``ConsistentHashable`` itself,
while the ``Entry`` message is wrapped in a ``ConsistentHashableEnvelope``. The ``Evict`` while the ``Entry`` message is wrapped in a ``ConsistentHashableEnvelope``. The ``Evict``

View file

@ -11,7 +11,6 @@ object ConsistentHashingRouterDocSpec {
//#cache-actor //#cache-actor
import akka.actor.Actor import akka.actor.Actor
import akka.routing.ConsistentHashingRouter.ConsistentHashable import akka.routing.ConsistentHashingRouter.ConsistentHashable
import akka.routing.ConsistentHashingRouter.ConsistentHashableEnvelope
class Cache extends Actor { class Cache extends Actor {
var cache = Map.empty[String, String] var cache = Map.empty[String, String]

View file

@ -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. 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 * 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. 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 The key is part of the message and it's convenient to define it together
with the message definition. with the message definition.