bitcoin-atm
bitcoin atm for pyc inc.
git clone https://9o.is/git/bitcoin-atm.git
commit 2adc6b793d284eac9e3d0f727760b76c995c150f parent 56184dc361c32a561d0b75926f129690c001f42f Author: Jul <jul@9o.is> Date: Mon, 4 Aug 2014 18:20:45 -0700 redirects to /disconnected when network is unreachabled Diffstat:
| M | src/main/scala/bootstrap/liftweb/Boot.scala | | | 5 | +++++ |
| A | src/main/scala/inc/pyc/chimera/snippet/Network.scala | | | 120 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
| M | src/main/scala/inc/pyc/chimera/snippet/Transaction.scala | | | 27 | +++++++++++---------------- |
| M | src/main/webapp/app/ActorsBridge.js | | | 9 | +++++++++ |
| A | src/main/webapp/disconnected.html | | | 4 | ++++ |
| M | src/main/webapp/index.html | | | 6 | ++++++ |
| M | src/main/webapp/templates-hidden/base-wrap.html | | | 3 | +-- |
7 files changed, 156 insertions(+), 18 deletions(-)
diff --git a/src/main/scala/bootstrap/liftweb/Boot.scala b/src/main/scala/bootstrap/liftweb/Boot.scala @@ -16,6 +16,7 @@ import config._ import bitcoin._ import PriceTicker.commands._ import Wallet.commands._ +import snippet.{Network, TransactionState} /** * A class that's instantiated early and run. It allows the application @@ -37,6 +38,7 @@ class Boot extends Loggable { // Build SiteMap LiftRules.setSiteMap(SiteMap(List( Menu.i("Bitcoin ATM") / "index", + Menu.i("Disconnected") / "disconnected", Menu.i("Error") / "error" >> Hidden, Menu.i("404") / "404" >> Hidden ): _*)) @@ -68,11 +70,14 @@ class Boot extends Loggable { BitcoinServices.system.shutdown() Lycia.system.shutdown() + Network.system.shutdown() + TransactionState.system.shutdown() } // Initialize actors PriceTicker ! Tick Wallet ! InitBalance + Network ! "init" } def setDB(): Unit = { diff --git a/src/main/scala/inc/pyc/chimera/snippet/Network.scala b/src/main/scala/inc/pyc/chimera/snippet/Network.scala @@ -0,0 +1,119 @@ +package inc.pyc.chimera +package snippet + +import xml._ +import model._ +import akka.actor._ +import akka.agent._ +import dispatch._, Defaults._ +import scala.concurrent.duration._ +import org.joda.time.DateTime + +/** + * Checking network connectivity every n seconds. + */ +object Network { + + def !(any: Any): Unit = actor ! any + + /** + * Transaction State Actor System + */ + val system = ActorSystem("TransactionSystem") + + + /** + * Event Bus for Transaction State. + */ + val bus = new LookupTransaction + + /** + * The main actor that handles communications. + */ + private val actor = system.actorOf(Props[Network], "NetworkChecker") + + /** + * The ticker that checks network connection every 20 seconds. + */ + private val ticker = + system.scheduler.schedule(0 milliseconds, 20 seconds, actor, commands.Ping) + + /** + * Subscription topics for event bus. + */ + object topics { + val redirectTo = "redirectTo" + } + + object commands { + case object Ping + } +} + + +/** + * PubSub for network. + */ +class LookupNetwork extends LiftActorEventBus { + // redirectTo + override protected def mapSize: Int = 1 +} + +class Network extends Actor with ActorLogging { + import Network.commands._ + import Network.topics._ + + val ping = "https://www.google.com/" + + def receive: Receive = { + case Ping => + check(ping, fail = Some("/disconnected")) + + case "init" => + log.info("Network Connectivity Actor Activated") + } + + def disconnected: Receive = { + case Ping => + check(ping, succeed = Some("/index")) + } + + def check(link: String, fail: Option[String] = None, succeed: Option[String] = None) { + Http(url(link) OK as.String).either() match { + case Left(_) => + fail map { + redirect => + log.info("Network unreachable: redirecting to {}", redirect) + context.become(disconnected) + Network.bus.publish(EventUpdate(redirectTo, redirect)) + } + + case Right(_) => + succeed map { + redirect => + log.info("Network reconnected: redirecting to {}", redirect) + context.become(receive) + Network.bus.publish(EventUpdate(redirectTo, redirect)) + } + } + } +} + +/** + * Snippet for updates on network connectivity. + */ +class NetworkComet extends EventRegister { + + implicit val system = Network.system + + val bus = Network.bus + + val topics: List[(String, () => Unit)] = List( + (Network.topics.redirectTo, () => {})) + + + + override def render(o: NodeSeq): NodeSeq = { + super.render(o) + } +} +\ No newline at end of file diff --git a/src/main/scala/inc/pyc/chimera/snippet/Transaction.scala b/src/main/scala/inc/pyc/chimera/snippet/Transaction.scala @@ -6,12 +6,15 @@ import model._ import akka.actor._ import akka.agent._ - +/** + * Handling state of the current transaction. + */ object TransactionState { - import InternalTransactionState._ - import system.dispatcher - val currentTransaction: Agent[Transaction] = Agent(Transaction.create) + /** + * Transaction State Actor System + */ + val system = ActorSystem("TransactionSystem") /** * Event Bus for Transaction State. @@ -24,18 +27,10 @@ object TransactionState { object topics { val transactionUpdate = "transactionUpdate" } -} - - -/** - * Handling state of the current transaction. - */ -private object InternalTransactionState { - /** - * Transaction State Actor System - */ - implicit val system = ActorSystem("TransactionSystem") + import system.dispatcher + + val currentTransaction: Agent[Transaction] = Agent(Transaction.create) } @@ -52,7 +47,7 @@ class LookupTransaction extends LiftActorEventBus { */ class TransactionComet extends EventRegister { - implicit val system = InternalTransactionState.system + val system = TransactionState.system val bus = TransactionState.txBus diff --git a/src/main/webapp/app/ActorsBridge.js b/src/main/webapp/app/ActorsBridge.js @@ -32,4 +32,13 @@ window.ActorsBridge = function(sendFunc) { self.broadcast('transactionUpdate', message); }; + /** + * Used for page redirection. For example, when the network + * is down, the page will redirect to the appropriate page. + */ + self.redirectTo = function(message) { + window.console.log(message); + window.location = message; + }; + }; \ No newline at end of file diff --git a/src/main/webapp/disconnected.html b/src/main/webapp/disconnected.html @@ -0,0 +1,3 @@ +<div data-lift="surround?with=base-default;at=content"> + <p style="font-size: 1.2em;">We're sorry but there's no Internet.</p> +</div> +\ No newline at end of file diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html @@ -28,4 +28,10 @@ </wz-step> </wizard> +<!-- Comets --> +<div data-lift="tail"> + <script data-lift="PriceTickerComet"></script> + <script data-lift="TransactionComet"></script> +</div> + </div> \ No newline at end of file diff --git a/src/main/webapp/templates-hidden/base-wrap.html b/src/main/webapp/templates-hidden/base-wrap.html @@ -36,8 +36,7 @@ <script data-lift="Assets.js" type="text/javascript"></script> <!-- Comets --> -<script data-lift="PriceTickerComet"></script> -<script data-lift="TransactionComet"></script> +<script data-lift="NetworkComet"></script> </body> </html>