package service
package user
-import java.util.Date
-import com.ckkloverdos.maybe.{Failed, NoVal, Just}
-
import gr.grnet.aquarium.actor._
-import gr.grnet.aquarium.Configurator
-import gr.grnet.aquarium.user._
-import gr.grnet.aquarium.util.Loggable
+import gr.grnet.aquarium.actor.message.event.{ProcessResourceEvent, ProcessIMEvent}
+import gr.grnet.aquarium.actor.message.config.{InitializeUserActorState, AquariumPropertiesLoaded}
import gr.grnet.aquarium.util.date.TimeHelpers
-import gr.grnet.aquarium.logic.accounting.RoleAgreements
-import gr.grnet.aquarium.messaging.AkkaAMQP
-import gr.grnet.aquarium.actor.message.config.user.UserActorInitWithUserId
-import gr.grnet.aquarium.actor.message.service.router._
-import message.config.{ActorProviderConfigured, AquariumPropertiesLoaded}
-import gr.grnet.aquarium.event.im.IMEventModel
-import gr.grnet.aquarium.event.{WalletEntry}
-
+import gr.grnet.aquarium.service.event.BalanceEvent
+import gr.grnet.aquarium.event.model.im.IMEventModel
+import message._
+import config.AquariumPropertiesLoaded
+import config.InitializeUserActorState
+import event.ProcessIMEvent
+import event.ProcessResourceEvent
+import gr.grnet.aquarium.util.{LogHelpers, shortClassNameOf}
+import gr.grnet.aquarium.{Aquarium, AquariumInternalError}
+import gr.grnet.aquarium.computation.BillingMonthInfo
+import gr.grnet.aquarium.charging.state.UserStateBootstrap
+import gr.grnet.aquarium.charging.state.{WorkingAgreementHistory, WorkingUserState, UserStateModel}
+import gr.grnet.aquarium.charging.reason.{InitialUserActorSetup, RealtimeChargingReason}
+import gr.grnet.aquarium.policy.{PolicyDefinedFullPriceTableRef, StdUserAgreement}
+import gr.grnet.aquarium.event.model.resource.{StdResourceEvent, ResourceEventModel}
+import message.GetUserBalanceRequest
+import message.GetUserBalanceResponse
+import message.GetUserBalanceResponseData
+import message.GetUserStateRequest
+import message.GetUserStateResponse
+import message.GetUserWalletRequest
+import message.GetUserWalletResponse
+import message.GetUserWalletResponseData
+import scala.Left
+import gr.grnet.aquarium.charging.state.WorkingAgreementHistory
+import scala.Some
+import scala.Right
+import gr.grnet.aquarium.policy.StdUserAgreement
+import gr.grnet.aquarium.charging.state.UserStateBootstrap
+import gr.grnet.aquarium.charging.bill.BillEntry
/**
*
* @author Christos KK Loverdos <loverdos@gmail.com>
*/
-class UserActor extends AquariumActor
-with AkkaAMQP
-with ReflectiveAquariumActor
-with Loggable {
- @volatile
- private[this] var _userId: String = _
- @volatile
- private[this] var _userState: UserState = _
- @volatile
- private[this] var _timestampTheshold: Long = _
+class UserActor extends ReflectiveRoleableActor {
+ private[this] var _userID: String = "<?>"
+ private[this] var _workingUserState: WorkingUserState = _
+ private[this] var _userCreationIMEvent: IMEventModel = _
+ private[this] val _workingAgreementHistory: WorkingAgreementHistory = new WorkingAgreementHistory
+ private[this] var _latestIMEventID: String = ""
+ private[this] var _latestResourceEventID: String = ""
+ private[this] var _userStateBootstrap: UserStateBootstrap = _
+
+ def unsafeUserID = {
+ if(!haveUserID) {
+ throw new AquariumInternalError("%s not initialized")
+ }
+
+ this._userID
+ }
+
+ override def postStop() {
+ DEBUG("I am finally stopped (in postStop())")
+ aquarium.akkaService.notifyUserActorPostStop(this)
+ }
+
+ private[this] def shutmedown(): Unit = {
+ if(haveUserID) {
+ aquarium.akkaService.invalidateUserActor(this)
+ }
+ }
+
+ override protected def onThrowable(t: Throwable, message: AnyRef) = {
+ LogHelpers.logChainOfCauses(logger, t)
+ ERROR(t, "Terminating due to: %s(%s)", shortClassNameOf(t), t.getMessage)
- private[this] lazy val messenger = producer("aquarium") // FIXME: Read this from configuration
+ shutmedown()
+ }
def role = UserActorRole
- private[this] def _configurator: Configurator = Configurator.MasterConfigurator
+ private[this] def chargingService = aquarium.chargingService
- /**
- * Replay the event log for all events that affect the user state.
- */
- def rebuildState(from: Long, to: Long): Unit = {
- val start = TimeHelpers.nowMillis()
- if(_userState == null)
- createBlankState
-
- //Rebuild state from user events
- val usersDB = _configurator.storeProvider.imEventStore
- val userEvents = usersDB.findIMEventsByUserId(_userId)
- val numUserEvents = userEvents.size
- _userState = replayIMEvents(_userState, userEvents, from, to)
-
- //Rebuild state from resource events
- val eventsDB = _configurator.storeProvider.resourceEventStore
- val resourceEvents = eventsDB.findResourceEventsByUserIdAfterTimestamp(_userId, from)
- val numResourceEvents = resourceEvents.size
- // _userState = replayResourceEvents(_userState, resourceEvents, from, to)
-
- //Rebuild state from wallet entries
- val wallet = _configurator.storeProvider.walletEntryStore
- val walletEnties = wallet.findWalletEntriesAfter(_userId, new Date(from))
- val numWalletEntries = walletEnties.size
- _userState = replayWalletEntries(_userState, walletEnties, from, to)
-
- INFO(("Rebuilt state from %d events (%d user events, " +
- "%d resource events, %d wallet entries) in %d msec").format(
- numUserEvents + numResourceEvents + numWalletEntries,
- numUserEvents, numResourceEvents, numWalletEntries,
- TimeHelpers.nowMillis() - start))
+ private[this] def stdUserStateStoreFunc = (userState: UserStateModel) ⇒ {
+ aquarium.userStateStore.insertUserState(userState)
}
- /**
- * Create an empty state for a user
- */
- def createBlankState = {
- this._userState = DefaultUserStateComputations.createInitialUserState(this._userId, 0L, true, 0.0)
+ @inline private[this] def haveUserID = {
+ this._userID ne null
}
- /**
- * Replay user events on the provided user state
- */
- def replayIMEvents(initState: UserState, events: List[IMEventModel],
- from: Long, to: Long): UserState = {
- initState
+ @inline private[this] def haveUserCreationIMEvent = {
+ this._userCreationIMEvent ne null
+ }
+
+ def onAquariumPropertiesLoaded(event: AquariumPropertiesLoaded): Unit = {
}
+ @inline private[this] def haveAgreements = {
+ this._workingAgreementHistory.size > 0
+ }
- /**
- * Replay wallet entries on the provided user state
- */
- def replayWalletEntries(initState: UserState, events: List[WalletEntry],
- from: Long, to: Long): UserState = {
- initState
+ @inline private[this] def haveWorkingUserState = {
+ this._workingUserState ne null
}
- /**
- * Persist current user state
- */
- private[this] def saveUserState(): Unit = {
- _configurator.storeProvider.userStateStore.storeUserState(this._userState) match {
- case Just(record) => record
- case NoVal => ERROR("Unknown error saving state")
- case Failed(e) =>
- ERROR("Saving state failed: %s".format(e));
+ @inline private[this] def haveUserStateBootstrap = {
+ this._userStateBootstrap ne null
+ }
+
+ private[this] def updateAgreementHistoryFrom(imEvent: IMEventModel): Unit = {
+ if(imEvent.isCreateUser) {
+ if(haveUserCreationIMEvent) {
+ throw new AquariumInternalError(
+ "Got user creation event (id=%s) but I already have one (id=%s)",
+ this._userCreationIMEvent.id,
+ imEvent.id
+ )
+ }
+
+ this._userCreationIMEvent = imEvent
}
+
+ val effectiveFromMillis = imEvent.occurredMillis
+ val role = imEvent.role
+ // calling unsafe just for the side-effect
+ assert(null ne aquarium.unsafePriceTableForRoleAt(role, effectiveFromMillis))
+
+ val newAgreement = StdUserAgreement(
+ imEvent.id,
+ Some(imEvent.id),
+ effectiveFromMillis,
+ Long.MaxValue,
+ role,
+ PolicyDefinedFullPriceTableRef
+ )
+
+ this._workingAgreementHistory += newAgreement
}
- def onAquariumPropertiesLoaded(event: AquariumPropertiesLoaded): Unit = {
- this._timestampTheshold = event.props.getLong(Configurator.Keys.user_state_timestamp_threshold).getOr(10000)
- INFO("Setup my timestampTheshold = %s", this._timestampTheshold)
+ private[this] def updateLatestIMEventIDFrom(imEvent: IMEventModel): Unit = {
+ this._latestIMEventID = imEvent.id
}
- def onUserActorInitWithUserId(event: UserActorInitWithUserId): Unit = {
- this._userId = event.userId
- DEBUG("Actor starting, loading state")
+ private[this] def updateLatestResourceEventIDFrom(rcEvent: ResourceEventModel): Unit = {
+ this._latestResourceEventID = rcEvent.id
}
- def onProcessResourceEvent(event: ProcessResourceEvent): Unit = {
- val resourceEvent = event.rcEvent
- if(resourceEvent.userID != this._userId) {
- ERROR("Received %s but my userId = %s".format(event, this._userId))
- } else {
- //ensureUserState()
- // calcWalletEntries()
- //processResourceEvent(resourceEvent, true)
+ /**
+ * Creates the initial state that is related to IMEvents.
+ */
+ private[this] def initializeStateOfIMEvents(): Unit = {
+ // NOTE: this._userID is already set up by onInitializeUserActorState()
+ aquarium.imEventStore.foreachIMEventInOccurrenceOrder(this._userID) { imEvent ⇒
+ DEBUG("Replaying %s", imEvent)
+
+ updateAgreementHistoryFrom(imEvent)
+ updateLatestIMEventIDFrom(imEvent)
}
- }
- private[this] def processCreateUser(event: IMEventModel): Unit = {
- val userId = event.userID
- DEBUG("Creating user from state %s", event)
- val usersDB = _configurator.storeProvider.userStateStore
- usersDB.findUserStateByUserId(userId) match {
- case Just(userState) ⇒
- WARN("User already created, state = %s".format(userState))
- case failed@Failed(e) ⇒
- ERROR("[%s] %s", e.getClass.getName, e.getMessage)
- case NoVal ⇒
- val agreement = RoleAgreements.agreementForRole(event.role)
- DEBUG("User %s assigned agreement %s".format(userId, agreement.name))
-
- this._userState = DefaultUserStateComputations.createInitialUserState(
- userId,
- event.occurredMillis,
- event.isActive, 0.0, List(event.role), agreement.name)
- saveUserState
- DEBUG("Created and stored %s", this._userState)
+ if(haveAgreements) {
+ DEBUG("Initial agreement history %s", this._workingAgreementHistory.toJsonString)
+ logSeparator()
}
}
- private[this] def processModifyUser(event: IMEventModel): Unit = {
+ /**
+ * Resource events are processed only if the user has been created and has agreements.
+ * Otherwise nothing can be computed.
+ */
+ private[this] def shouldProcessResourceEvents: Boolean = {
+ haveUserCreationIMEvent && haveAgreements && haveUserStateBootstrap
+ }
+
+ private[this] def loadWorkingUserStateAndUpdateAgreementHistory(): Unit = {
+ assert(this.haveAgreements, "this.haveAgreements")
+ assert(this.haveUserCreationIMEvent, "this.haveUserCreationIMEvent")
+
+ val userCreationMillis = this._userCreationIMEvent.occurredMillis
+ val userCreationRole = this._userCreationIMEvent.role // initial role
+ val userCreationIMEventID = this._userCreationIMEvent.id
+
+ if(!haveUserStateBootstrap) {
+ this._userStateBootstrap = UserStateBootstrap(
+ this._userID,
+ userCreationMillis,
+ aquarium.initialUserAgreement(userCreationRole, userCreationMillis, Some(userCreationIMEventID)),
+ aquarium.initialUserBalance(userCreationRole, userCreationMillis)
+ )
+ }
+
val now = TimeHelpers.nowMillis()
- val newActive = ActiveStateSnapshot(event.isStateActive, now)
+ this._workingUserState = chargingService.replayMonthChargingUpTo(
+ BillingMonthInfo.fromMillis(now),
+ now,
+ this._userStateBootstrap,
+ aquarium.currentResourceTypesMap,
+ InitialUserActorSetup(),
+ aquarium.userStateStore.insertUserState
+ )
+
+ // Final touch: Update agreement history in the working user state.
+ // The assumption is that all agreement changes go via IMEvents, so the
+ // state this._workingAgreementHistory is always the authoritative source.
+ if(haveWorkingUserState) {
+ this._workingUserState.workingAgreementHistory.setFrom(this._workingAgreementHistory)
+ DEBUG("Computed working user state %s", this._workingUserState.toJsonString)
+ }
+ }
+
+ private[this] def initializeStateOfResourceEvents(event: InitializeUserActorState): Unit = {
+ if(!this.haveAgreements) {
+ DEBUG("Cannot initializeResourceEventsState() from %s. There are no agreements", event)
+ return
+ }
+
+ if(!this.haveUserCreationIMEvent) {
+ DEBUG("Cannot initializeResourceEventsState() from %s. I never got a CREATE IMEvent", event)
+ return
+ }
+
+ // We will also need this functionality when receiving IMEvents, so we place it in a method
+ loadWorkingUserStateAndUpdateAgreementHistory()
- DEBUG("New active status = %s".format(newActive))
+ if(haveWorkingUserState) {
+ DEBUG("Initial working user state %s", this._workingUserState.toJsonString)
+ logSeparator()
+ }
+ }
+
+ def onInitializeUserActorState(event: InitializeUserActorState): Unit = {
+ this._userID = event.userID
+ DEBUG("Got %s", event)
- this._userState = this._userState.copy(activeStateSnapshot = newActive)
+ initializeStateOfIMEvents()
+ initializeStateOfResourceEvents(event)
}
- def onProcessIMEvent(event: ProcessIMEvent): Unit = {
- val userEvent = event.imEvent
- if(userEvent.userID != this._userId) {
- ERROR("Received %s but my userId = %s".format(userEvent, this._userId))
- } else {
- if(userEvent.isCreateUser) {
- processCreateUser(userEvent)
- } else if(userEvent.isModifyUser) {
- processModifyUser(userEvent)
+ /**
+ * Process [[gr.grnet.aquarium.event.model.im.IMEventModel]]s.
+ * When this method is called, we assume that all proper checks have been made and it
+ * is OK to proceed with the event processing.
+ */
+ def onProcessIMEvent(processEvent: ProcessIMEvent): Unit = {
+ val imEvent = processEvent.imEvent
+ val hadUserCreationIMEvent = haveUserCreationIMEvent
+
+ if(!haveAgreements) {
+ // This IMEvent has arrived after any ResourceEvents
+ INFO("Arrived after any ResourceEvent: %s", imEvent.toDebugString)
+ initializeStateOfIMEvents()
+ }
+ else {
+ if(this._latestIMEventID == imEvent.id) {
+ // This happens when the actor is brought to life, then immediately initialized, and then
+ // sent the first IM event. But from the initialization procedure, this IM event will have
+ // already been loaded from DB!
+ INFO("Ignoring first %s", imEvent.toDebugString)
+ logSeparator()
+
+ //this._latestIMEventID = imEvent.id
+ return
+ }
+ if(imEvent.isAddCredits) {
+ if(!hadUserCreationIMEvent && haveUserCreationIMEvent)
+ loadWorkingUserStateAndUpdateAgreementHistory()
+ onHandleAddCreditsEvent(imEvent)
+
+ } else {
+ updateAgreementHistoryFrom(imEvent)
+ updateLatestIMEventIDFrom(imEvent)
}
}
+
+ // Must also update user state if we know when in history the life of a user begins
+ if(!hadUserCreationIMEvent && haveUserCreationIMEvent) {
+ INFO("Processing user state, since we had a CREATE IMEvent")
+ loadWorkingUserStateAndUpdateAgreementHistory()
+ }
+
+ logSeparator()
}
- def onRequestUserBalance(event: RequestUserBalance): Unit = {
- val userId = event.userId
- val timestamp = event.timestamp
+ /* Convert astakos message for adding credits
+ to a regular RESOURCE message */
+ def onHandleAddCreditsEvent(imEvent : IMEventModel) = {
+ val credits = imEvent.details(IMEventModel.DetailsNames.credits).toInt.toDouble
+ val event = new StdResourceEvent(
+ imEvent.id,
+ imEvent.occurredMillis,
+ imEvent.receivedMillis,
+ imEvent.userID,
+ imEvent.clientID,
+ imEvent.eventType,
+ imEvent.eventType,
+ credits,
+ imEvent.eventVersion,
+ imEvent.details
+ )
+ //Console.err.println("Event: " + event)
+ //Console.err.println("Total credits before: " + _workingUserState.totalCredits)
+ onProcessResourceEvent(new ProcessResourceEvent(event))
+ //Console.err.println("Total credits after: " + _workingUserState.totalCredits)
+ //Console.err.println("OK.")
+ }
+
+ def onProcessResourceEvent(event: ProcessResourceEvent): Unit = {
+ val rcEvent = event.rcEvent
+
+ if(!shouldProcessResourceEvents) {
+ // This means the user has not been created (at least, as far as Aquarium is concerned).
+ // So, we do not process any resource event
+ DEBUG("Not processing %s", rcEvent.toJsonString)
+ logSeparator()
+
+ return
+ }
+
+ // Since the latest resource event per resource is recorded in the user state,
+ // we do not need to query the store. Just query the in-memory state.
+ // Note: This is a similar situation with the first IMEvent received right after the user
+ // actor is created.
+ if(this._latestResourceEventID == rcEvent.id) {
+ INFO("Ignoring first %s", rcEvent.toDebugString)
+ logSeparator()
+
+ return
+ }
+
+ val now = TimeHelpers.nowMillis()
+ val currentResourcesMap = aquarium.currentResourceTypesMap
+ val chargingReason = RealtimeChargingReason(None, now)
+
+ val nowBillingMonthInfo = BillingMonthInfo.fromMillis(now)
+ val nowYear = nowBillingMonthInfo.year
+ val nowMonth = nowBillingMonthInfo.month
+
+ val eventOccurredMillis = rcEvent.occurredMillis
+ val eventBillingMonthInfo = BillingMonthInfo.fromMillis(eventOccurredMillis)
+ val eventYear = eventBillingMonthInfo.year
+ val eventMonth = eventBillingMonthInfo.month
+
+ def computeBatch(): Unit = {
+ DEBUG("Going for out of sync charging")
+ this._workingUserState = chargingService.replayMonthChargingUpTo(
+ nowBillingMonthInfo,
+ // Take into account that the event may be out-of-sync.
+ // TODO: Should we use this._latestResourceEventOccurredMillis instead of now?
+ now max eventOccurredMillis,
+ this._userStateBootstrap,
+ currentResourcesMap,
+ chargingReason,
+ stdUserStateStoreFunc
+ )
+
+ updateLatestResourceEventIDFrom(rcEvent)
+ }
- if(TimeHelpers.nowMillis() - _userState.newestSnapshotTime > 60 * 1000) {
- // calcWalletEntries()
+ def computeRealtime(): Unit = {
+ DEBUG("Going for in sync charging")
+ chargingService.processResourceEvent(
+ rcEvent,
+ this._workingUserState,
+ chargingReason,
+ nowBillingMonthInfo,
+ true
+ )
+
+ updateLatestResourceEventIDFrom(rcEvent)
+ }
+
+ var oldTotalCredits = this._workingUserState.totalCredits
+ // FIXME check these
+ if(nowYear != eventYear || nowMonth != eventMonth) {
+ DEBUG(
+ "nowYear(%s) != eventYear(%s) || nowMonth(%s) != eventMonth(%s)",
+ nowYear, eventYear,
+ nowMonth, eventMonth
+ )
+ computeBatch()
+ }
+ else if(this._workingUserState.latestResourceEventOccurredMillis < rcEvent.occurredMillis) {
+ DEBUG("this._workingUserState.latestResourceEventOccurredMillis < rcEvent.occurredMillis")
+ DEBUG(
+ "%s < %s",
+ TimeHelpers.toYYYYMMDDHHMMSSSSS(this._workingUserState.latestResourceEventOccurredMillis),
+ TimeHelpers.toYYYYMMDDHHMMSSSSS(rcEvent.occurredMillis)
+ )
+ computeRealtime()
}
- self reply UserResponseGetBalance(userId, _userState.creditsSnapshot.creditAmount)
+ else {
+ computeBatch()
+ }
+ var newTotal = this._workingUserState.totalCredits
+ if(oldTotalCredits * newTotal < 0)
+ aquarium.eventBus ! new BalanceEvent(this._workingUserState.userID,
+ newTotal>=0)
+ DEBUG("Updated %s", this._workingUserState)
+ logSeparator()
}
- def onUserRequestGetState(event: UserRequestGetState): Unit = {
- val userId = event.userId
- if(this._userId != userId) {
- ERROR("Received %s but my userId = %s".format(event, this._userId))
- // TODO: throw an exception here
- } else {
- // FIXME: implement
- ERROR("FIXME: Should have properly computed the user state")
- // ensureUserState()
- self reply UserResponseGetState(userId, this._userState)
+ def onGetUserBillRequest(event: GetUserBillRequest): Unit = {
+ try{
+ val timeslot = event.timeslot
+ val state= if(haveWorkingUserState) Some(this._workingUserState) else None
+ val billEntry = BillEntry.fromWorkingUserState(timeslot,this._userID,state)
+ val billData = GetUserBillResponseData(this._userID,billEntry)
+ sender ! GetUserBillResponse(Right(billData))
+ } catch {
+ case e:Exception =>
+ e.printStackTrace()
+ sender ! GetUserBillResponse(Left("Internal Server Error [AQU-BILL-0001]"), 500)
}
}
- def onActorProviderConfigured(event: ActorProviderConfigured): Unit = {
+ def onGetUserBalanceRequest(event: GetUserBalanceRequest): Unit = {
+ val userID = event.userID
+
+ (haveUserCreationIMEvent, haveWorkingUserState) match {
+ case (true, true) ⇒
+ // (User CREATEd, with balance state)
+ sender ! GetUserBalanceResponse(Right(GetUserBalanceResponseData(this._userID, this._workingUserState.totalCredits)))
+
+ case (true, false) ⇒
+ // (User CREATEd, no balance state)
+ // Return the default initial balance
+ sender ! GetUserBalanceResponse(
+ Right(
+ GetUserBalanceResponseData(
+ this._userID,
+ aquarium.initialUserBalance(this._userCreationIMEvent.role, this._userCreationIMEvent.occurredMillis)
+ )))
+
+ case (false, true) ⇒
+ // (Not CREATEd, with balance state)
+ // Clearly this is internal error
+ sender ! GetUserBalanceResponse(Left("Internal Server Error [AQU-BAL-0001]"), 500)
+
+ case (false, false) ⇒
+ // (Not CREATEd, no balance state)
+ // The user is completely unknown
+ sender ! GetUserBalanceResponse(Left("Unknown user %s [AQU-BAL-0004]".format(userID)), 404/*Not found*/)
+ }
}
- override def postStop {
- DEBUG("Actor[%s] stopping, saving state", self.uuid)
- saveUserState
+ def onGetUserStateRequest(event: GetUserStateRequest): Unit = {
+ haveWorkingUserState match {
+ case true ⇒
+ sender ! GetUserStateResponse(Right(this._workingUserState))
+
+ case false ⇒
+ sender ! GetUserStateResponse(Left("No state for user %s [AQU-STA-0006]".format(event.userID)), 404)
+ }
}
- override def preRestart(reason: Throwable) {
- ERROR(reason, "preRestart: Actor[%s]", self.uuid)
+ def onGetUserWalletRequest(event: GetUserWalletRequest): Unit = {
+ haveWorkingUserState match {
+ case true ⇒
+ DEBUG("haveWorkingUserState: %s", event)
+ sender ! GetUserWalletResponse(
+ Right(
+ GetUserWalletResponseData(
+ this._userID,
+ this._workingUserState.totalCredits,
+ this._workingUserState.walletEntries.toList
+ )))
+
+ case false ⇒
+ DEBUG("!haveWorkingUserState: %s", event)
+ haveUserCreationIMEvent match {
+ case true ⇒
+ DEBUG("haveUserCreationIMEvent: %s", event)
+ sender ! GetUserWalletResponse(
+ Right(
+ GetUserWalletResponseData(
+ this._userID,
+ aquarium.initialUserBalance(this._userCreationIMEvent.role, this._userCreationIMEvent.occurredMillis),
+ Nil
+ )))
+
+ case false ⇒
+ DEBUG("!haveUserCreationIMEvent: %s", event)
+ sender ! GetUserWalletResponse(Left("No wallet for user %s [AQU-WAL-00 8]".format(event.userID)), 404)
+ }
+ }
}
- override def postRestart(reason: Throwable) {
- ERROR(reason, "postRestart: Actor[%s]", self.uuid)
+ private[this] def D_userID = {
+ this._userID
}
private[this] def DEBUG(fmt: String, args: Any*) =
- logger.debug("UserActor[%s]: %s".format(_userId, fmt.format(args: _*)))
+ logger.debug("[%s] - %s".format(D_userID, fmt.format(args: _*)))
private[this] def INFO(fmt: String, args: Any*) =
- logger.info("UserActor[%s]: %s".format(_userId, fmt.format(args: _*)))
+ logger.info("[%s] - %s".format(D_userID, fmt.format(args: _*)))
private[this] def WARN(fmt: String, args: Any*) =
- logger.warn("UserActor[%s]: %s".format(_userId, fmt.format(args: _*)))
+ logger.warn("[%s] - %s".format(D_userID, fmt.format(args: _*)))
private[this] def ERROR(fmt: String, args: Any*) =
- logger.error("UserActor[%s]: %s".format(_userId, fmt.format(args: _*)))
+ logger.error("[%s] - %s".format(D_userID, fmt.format(args: _*)))
private[this] def ERROR(t: Throwable, fmt: String, args: Any*) =
- logger.error("UserActor[%s]: %s".format(_userId, fmt.format(args: _*)), t)
+ logger.error("[%s] - %s".format(D_userID, fmt.format(args: _*)), t)
}