PageRenderTime 103ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/akka-amqp/src/main/scala/akka/amqp/rpc/RPC.scala

https://github.com/apeshimam/akka-modules
Scala | 352 lines | 269 code | 59 blank | 24 comment | 0 complexity | e02dbe36b9c4dec9572adcfa5cd67db0 MD5 | raw file
  1. package akka.amqp.rpc
  2. import akka.amqp.AMQP._
  3. import com.google.protobuf.Message
  4. import akka.actor.{Actor, ActorRef}
  5. import Actor._
  6. import akka.amqp._
  7. import reflect.Manifest
  8. import akka.japi
  9. object RPC {
  10. // Needed for Java API usage
  11. def newRpcClient[O, I](connection: ActorRef,
  12. exchangeName: String,
  13. routingKey: String,
  14. serializer: RpcClientSerializer[O, I]): RpcClient[O,I] = {
  15. newRpcClient(connection, exchangeName, serializer, Some(routingKey), None)
  16. }
  17. // Needed for Java API usage
  18. def newRpcClient[O, I](connection: ActorRef,
  19. exchangeName: String,
  20. routingKey: String,
  21. serializer: RpcClientSerializer[O, I],
  22. channelParameters: ChannelParameters): RpcClient[O,I] = {
  23. newRpcClient(connection, exchangeName, serializer, Some(routingKey), Some(channelParameters))
  24. }
  25. def newRpcClient[O, I](connection: ActorRef,
  26. exchangeName: String,
  27. serializer: RpcClientSerializer[O, I],
  28. routingKey: Option[String] = None,
  29. channelParameters: Option[ChannelParameters] = None): RpcClient[O,I] = {
  30. val rKey = routingKey.getOrElse("%s.request".format(exchangeName))
  31. val rpcActor: ActorRef = actorOf(new RpcClientActor[O, I](
  32. ExchangeParameters(exchangeName, exchangeDeclaration = PassiveDeclaration), rKey, serializer, channelParameters))
  33. connection.startLink(rpcActor)
  34. rpcActor ! Start
  35. rpcActor
  36. new RpcClient(rpcActor)
  37. }
  38. // Needed for Java API usage
  39. def newRpcServer[I, O](connection: ActorRef,
  40. exchangeName: String,
  41. serializer: RpcServerSerializer[I, O],
  42. requestHandler: japi.Function[I,O],
  43. routingKey: String): RpcServerHandle = {
  44. newRpcServer(connection, exchangeName, serializer, requestHandler.apply _, Some(routingKey))
  45. }
  46. // Needed for Java API usage
  47. def newRpcServer[I, O](connection: ActorRef,
  48. exchangeName: String,
  49. serializer: RpcServerSerializer[I, O],
  50. requestHandler: Function[I,O],
  51. routingKey: String,
  52. queueName: String): RpcServerHandle = {
  53. newRpcServer(connection, exchangeName, serializer, requestHandler.apply _, Some(routingKey), Some(queueName))
  54. }
  55. // Needed for Java API usage
  56. def newRpcServer[I, O](connection: ActorRef,
  57. exchangeName: String,
  58. serializer: RpcServerSerializer[I, O],
  59. requestHandler: japi.Function[I,O],
  60. routingKey: String,
  61. channelParameters: ChannelParameters): RpcServerHandle = {
  62. newRpcServer(connection, exchangeName, serializer, requestHandler.apply _, Some(routingKey), None, Some(channelParameters))
  63. }
  64. // Needed for Java API usage
  65. def newRpcServer[I, O](connection: ActorRef,
  66. exchangeName: String,
  67. serializer: RpcServerSerializer[I, O],
  68. requestHandler: japi.Function[I,O],
  69. routingKey: String,
  70. queueName: String,
  71. channelParameters: ChannelParameters): RpcServerHandle = {
  72. newRpcServer(connection, exchangeName, serializer, requestHandler.apply _, Some(routingKey), Some(queueName), Some(channelParameters))
  73. }
  74. def newRpcServer[I, O](connection: ActorRef,
  75. exchangeName: String,
  76. serializer: RpcServerSerializer[I, O],
  77. requestHandler: I => O,
  78. routingKey: Option[String] = None,
  79. queueName: Option[String] = None,
  80. channelParameters: Option[ChannelParameters] = None,
  81. poolSize: Int = 1): RpcServerHandle = {
  82. val rKey = routingKey.getOrElse("%s.request".format(exchangeName))
  83. val qName = queueName.getOrElse("%s.in".format(rKey))
  84. val producer = newProducer(connection, ProducerParameters(channelParameters = channelParameters))
  85. val consumers = (1 to poolSize).map {
  86. num =>
  87. val rpcServer = actorOf(new RpcServerActor[I, O](producer, serializer, requestHandler))
  88. newConsumer(connection, ConsumerParameters(rKey, rpcServer,
  89. exchangeParameters = Some(ExchangeParameters(exchangeName)), channelParameters = channelParameters,
  90. selfAcknowledging = false, queueName = Some(qName)))
  91. }
  92. RpcServerHandle(producer, consumers)
  93. }
  94. case class RpcServerHandle(producer: ActorRef, consumers: Seq[ActorRef]) {
  95. def stop = {
  96. consumers.foreach(_.stop)
  97. producer.stop
  98. }
  99. }
  100. case class RpcClientSerializer[O, I](toBinary: ToBinary[O], fromBinary: FromBinary[I])
  101. case class RpcServerSerializer[I, O](fromBinary: FromBinary[I], toBinary: ToBinary[O])
  102. /**
  103. * RPC convenience
  104. */
  105. class RpcClient[O, I](client: ActorRef){
  106. // Needed for Java API usage
  107. def call(request: O): Option[I] = {
  108. call(request, 5000)
  109. }
  110. def call(request: O, timeout: Long = 5000): Option[I] = {
  111. (client.!!(request, timeout)).as[I]
  112. }
  113. // Needed for Java API usage
  114. def callAsync(request: O, responseHandler: japi.Procedure[I]): Unit = {
  115. callAsync(request, 5000, responseHandler)
  116. }
  117. // Needed for Java API usage
  118. def callAsync(request: O, timeout: Long, responseHandler: japi.Procedure[I]): Unit = {
  119. callAsync(request, timeout){
  120. case Some(response) => responseHandler.apply(response)
  121. }
  122. }
  123. def callAsync(request: O, timeout: Long = 5000)(responseHandler: PartialFunction[Option[I],Unit]) = {
  124. spawn {
  125. val result = call(request, timeout)
  126. responseHandler.apply(result)
  127. }
  128. }
  129. def stop = client.stop
  130. }
  131. // Needed for Java API usage
  132. def newProtobufRpcServer[I <: Message, O <: Message](
  133. connection: ActorRef,
  134. exchangeName: String,
  135. requestHandler: japi.Function[I,O],
  136. resultClazz: Class[I]): RpcServerHandle = {
  137. implicit val manifest = Manifest.classType[I](resultClazz)
  138. newProtobufRpcServer(connection, exchangeName, requestHandler.apply _)
  139. }
  140. // Needed for Java API usage
  141. def newProtobufRpcServer[I <: Message, O <: Message](
  142. connection: ActorRef,
  143. exchangeName: String,
  144. requestHandler: japi.Function[I,O],
  145. routingKey: String,
  146. resultClazz: Class[I]): RpcServerHandle = {
  147. implicit val manifest = Manifest.classType[I](resultClazz)
  148. newProtobufRpcServer(connection, exchangeName, requestHandler.apply _, Some(routingKey))
  149. }
  150. // Needed for Java API usage
  151. def newProtobufRpcServer[I <: Message, O <: Message](
  152. connection: ActorRef,
  153. exchangeName: String,
  154. requestHandler: japi.Function[I,O],
  155. routingKey: String,
  156. queueName: String,
  157. resultClazz: Class[I]): RpcServerHandle = {
  158. implicit val manifest = Manifest.classType[I](resultClazz)
  159. newProtobufRpcServer(connection, exchangeName, requestHandler.apply _, Some(routingKey), Some(queueName))
  160. }
  161. // Needed for Java API usage
  162. def newProtobufRpcServer[I <: Message, O <: Message](
  163. connection: ActorRef,
  164. exchangeName: String,
  165. requestHandler: japi.Function[I,O],
  166. routingKey: String,
  167. queueName: String,
  168. channelParameters: ChannelParameters,
  169. resultClazz: Class[I]): RpcServerHandle = {
  170. implicit val manifest = Manifest.classType[I](resultClazz)
  171. newProtobufRpcServer(connection, exchangeName, requestHandler.apply _, Some(routingKey), Some(queueName), Some(channelParameters))
  172. }
  173. def newProtobufRpcServer[I <: Message, O <: Message](
  174. connection: ActorRef,
  175. exchangeName: String,
  176. requestHandler: I => O,
  177. routingKey: Option[String] = None,
  178. queueName: Option[String] = None,
  179. channelParameters: Option[ChannelParameters] = None,
  180. poolSize: Int = 1)(implicit manifest: Manifest[I]): RpcServerHandle = {
  181. val serializer = new RpcServerSerializer[I, O](
  182. new FromBinary[I] {
  183. def fromBinary(bytes: Array[Byte]): I = {
  184. createProtobufFromBytes[I](bytes)
  185. }
  186. }, new ToBinary[O] {
  187. def toBinary(t: O) = t.toByteArray
  188. })
  189. newRpcServer(connection, exchangeName, serializer, requestHandler, routingKey, queueName, channelParameters, poolSize)
  190. }
  191. // Needed for Java API usage
  192. def newProtobufRpcClient[O <: Message, I <: Message](
  193. connection: ActorRef,
  194. exchangeName: String,
  195. resultClazz: Class[I]): RpcClient[O, I] = {
  196. implicit val manifest = Manifest.classType[I](resultClazz)
  197. newProtobufRpcClient(connection, exchangeName, None)
  198. }
  199. // Needed for Java API usage
  200. def newProtobufRpcClient[O <: Message, I <: Message](
  201. connection: ActorRef,
  202. exchangeName: String,
  203. routingKey: String,
  204. resultClazz: Class[I]): RpcClient[O, I] = {
  205. implicit val manifest = Manifest.classType[I](resultClazz)
  206. newProtobufRpcClient(connection, exchangeName, Some(routingKey))
  207. }
  208. def newProtobufRpcClient[O <: Message, I <: Message](
  209. connection: ActorRef,
  210. exchangeName: String,
  211. routingKey: Option[String] = None)(implicit manifest: Manifest[I]): RpcClient[O, I] = {
  212. val serializer = new RpcClientSerializer[O, I](
  213. new ToBinary[O] {
  214. def toBinary(t: O) = t.toByteArray
  215. }, new FromBinary[I] {
  216. def fromBinary(bytes: Array[Byte]): I = {
  217. createProtobufFromBytes[I](bytes)
  218. }
  219. })
  220. newRpcClient(connection, exchangeName, serializer, routingKey)
  221. }
  222. // Needed for Java API usage
  223. def newStringRpcServer(connection: ActorRef,
  224. exchangeName: String,
  225. requestHandler: japi.Function[String,String]): RpcServerHandle = {
  226. newStringRpcServer(connection, exchangeName, requestHandler.apply _)
  227. }
  228. // Needed for Java API usage
  229. def newStringRpcServer(connection: ActorRef,
  230. exchangeName: String,
  231. requestHandler: japi.Function[String,String],
  232. routingKey: String): RpcServerHandle = {
  233. newStringRpcServer(connection, exchangeName, requestHandler.apply _, Some(routingKey))
  234. }
  235. // Needed for Java API usage
  236. def newStringRpcServer(connection: ActorRef,
  237. exchangeName: String,
  238. requestHandler: japi.Function[String,String],
  239. routingKey: String,
  240. queueName: String): RpcServerHandle = {
  241. newStringRpcServer(connection, exchangeName, requestHandler.apply _, Some(routingKey), Some(queueName))
  242. }
  243. // Needed for Java API usage
  244. def newStringRpcServer(connection: ActorRef,
  245. exchangeName: String,
  246. requestHandler: japi.Function[String,String],
  247. routingKey: String,
  248. queueName: String,
  249. channelParameters: ChannelParameters): RpcServerHandle = {
  250. newStringRpcServer(connection, exchangeName, requestHandler.apply _, Some(routingKey), Some(queueName), Some(channelParameters))
  251. }
  252. def newStringRpcServer(connection: ActorRef,
  253. exchangeName: String,
  254. requestHandler: String => String,
  255. routingKey: Option[String] = None,
  256. queueName: Option[String] = None,
  257. channelParameters: Option[ChannelParameters] = None,
  258. poolSize: Int = 1): RpcServerHandle = {
  259. val serializer = new RpcServerSerializer[String, String](
  260. new FromBinary[String] {
  261. def fromBinary(bytes: Array[Byte]): String = {
  262. new String(bytes)
  263. }
  264. }, new ToBinary[String] {
  265. def toBinary(t: String) = t.getBytes
  266. })
  267. newRpcServer(connection, exchangeName, serializer, requestHandler, routingKey, queueName, channelParameters, poolSize)
  268. }
  269. // Needed for Java API usage
  270. def newStringRpcClient(connection: ActorRef,
  271. exchange: String): RpcClient[String, String] = {
  272. newStringRpcClient(connection, exchange, None)
  273. }
  274. // Needed for Java API usage
  275. def newStringRpcClient(connection: ActorRef,
  276. exchange: String,
  277. routingKey: String): RpcClient[String, String] = {
  278. newStringRpcClient(connection, exchange, Some(routingKey))
  279. }
  280. def newStringRpcClient(connection: ActorRef,
  281. exchange: String,
  282. routingKey: Option[String] = None): RpcClient[String, String] = {
  283. val serializer = new RpcClientSerializer[String, String](
  284. new ToBinary[String] {
  285. def toBinary(t: String) = t.getBytes
  286. }, new FromBinary[String] {
  287. def fromBinary(bytes: Array[Byte]): String = {
  288. new String(bytes)
  289. }
  290. })
  291. newRpcClient(connection, exchange, serializer, routingKey)
  292. }
  293. }