Statistics
| Branch: | Tag: | Revision:

root / src / main / scala / gr / grnet / aquarium / actor / service / user / UserActor.scala @ d818f53c

History | View | Annotate | Download (5.6 kB)

1
/*
2
 * Copyright 2011-2012 GRNET S.A. All rights reserved.
3
 *
4
 * Redistribution and use in source and binary forms, with or
5
 * without modification, are permitted provided that the following
6
 * conditions are met:
7
 *
8
 *   1. Redistributions of source code must retain the above
9
 *      copyright notice, this list of conditions and the following
10
 *      disclaimer.
11
 *
12
 *   2. Redistributions in binary form must reproduce the above
13
 *      copyright notice, this list of conditions and the following
14
 *      disclaimer in the documentation and/or other materials
15
 *      provided with the distribution.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
18
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
24
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
25
 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28
 * POSSIBILITY OF SUCH DAMAGE.
29
 *
30
 * The views and conclusions contained in the software and
31
 * documentation are those of the authors and should not be
32
 * interpreted as representing official policies, either expressed
33
 * or implied, of GRNET S.A.
34
 */
35

    
36
package gr.grnet.aquarium.actor
37
package service
38
package user
39

    
40
import gr.grnet.aquarium.actor._
41
import gr.grnet.aquarium.user._
42

    
43
import gr.grnet.aquarium.util.shortClassNameOf
44
import message.config.{ActorProviderConfigured, AquariumPropertiesLoaded}
45
import gr.grnet.aquarium.event.im.IMEventModel
46
import akka.config.Supervision.Temporary
47
import gr.grnet.aquarium.Configurator
48
import gr.grnet.aquarium.util.date.{TimeHelpers, MutableDateCalc}
49
import gr.grnet.aquarium.actor.message.event.{ProcessResourceEvent, ProcessIMEvent}
50
import gr.grnet.aquarium.actor.message.{GetUserStateResponse, GetUserBalanceResponse, GetUserStateRequest, GetUserBalanceRequest}
51

    
52
/**
53
 *
54
 * @author Christos KK Loverdos <loverdos@gmail.com>
55
 */
56

    
57
class UserActor extends ReflectiveRoleableActor {
58
  private[this] var _imState: IMStateSnapshot = _
59
  private[this] var _userState: UserState = _
60

    
61
  self.lifeCycle = Temporary
62

    
63
  private[this] def _userID = this._userState.userID
64
  private[this] def _shutmedown(): Unit = {
65
    if(_haveUserState) {
66
      UserActorCache.invalidate(_userID)
67
    }
68

    
69
    self.stop()
70
  }
71

    
72
  override protected def onThrowable(t: Throwable, message: AnyRef) = {
73
    logChainOfCauses(t)
74
    ERROR(t, "Terminating due to: %s(%s)", shortClassNameOf(t), t.getMessage)
75

    
76
    _shutmedown()
77
  }
78

    
79
  def role = UserActorRole
80

    
81
  private[this] def _configurator: Configurator = Configurator.MasterConfigurator
82

    
83
  private[this] def _timestampTheshold =
84
    _configurator.props.getLong(Configurator.Keys.user_state_timestamp_threshold).getOr(10000)
85

    
86

    
87
  private[this] def _haveUserState = {
88
    this._userState ne null
89
  }
90

    
91
  private[this] def _haveIMState = {
92
    this._imState ne null
93
  }
94

    
95
  def onAquariumPropertiesLoaded(event: AquariumPropertiesLoaded): Unit = {
96
  }
97

    
98
  def onActorProviderConfigured(event: ActorProviderConfigured): Unit = {
99
  }
100

    
101
  private[this] def _getAgreementNameForNewUser(imEvent: IMEventModel): String = {
102
    // FIXME: Implement based on the role
103
    "default"
104
  }
105

    
106
  def onProcessIMEvent(event: ProcessIMEvent): Unit = {
107
    val now = TimeHelpers.nowMillis()
108

    
109
    val imEvent = event.imEvent
110
    val isUpdate = if(_haveIMState) {
111
      val newOccurredMillis = imEvent.occurredMillis
112
      val currentOccurredMillis = this._imState.imEvent.occurredMillis
113

    
114
      if(newOccurredMillis < currentOccurredMillis) {
115
        INFO(
116
          "Ignoring older IMEvent: [%s] < [%s]",
117
          new MutableDateCalc(newOccurredMillis).toYYYYMMDDHHMMSSSSS,
118
          new MutableDateCalc(currentOccurredMillis).toYYYYMMDDHHMMSSSSS)
119

    
120
        return
121
      }
122

    
123
      true
124
    } else {
125
      false
126
    }
127

    
128
    this._imState = IMStateSnapshot(imEvent, now)
129
    DEBUG("%s %s", if(isUpdate) "Update" else "Set", shortClassNameOf(this._imState))
130
  }
131

    
132
  def onGetUserBalanceRequest(event: GetUserBalanceRequest): Unit = {
133
    val userId = event.userID
134
    // FIXME: Implement
135
    self reply GetUserBalanceResponse(userId, Right(_userState.creditsSnapshot.creditAmount))
136
  }
137

    
138
  def onGetUserStateRequest(event: GetUserStateRequest): Unit = {
139
    val userId = event.userID
140
   // FIXME: Implement
141
    self reply GetUserStateResponse(userId, Right(this._userState))
142
  }
143

    
144
  def onProcessResourceEvent(event: ProcessResourceEvent): Unit = {
145
  }
146

    
147

    
148
  private[this] def D_userID = {
149
    if(this._userState eq null)
150
      if(this._imState eq null)
151
        "<NOT INITIALIZED>"
152
      else
153
        this._imState.imEvent.userID
154
    else
155
      this._userState.userID
156
  }
157

    
158
  private[this] def DEBUG(fmt: String, args: Any*) =
159
    logger.debug("UserActor[%s]: %s".format(D_userID, fmt.format(args: _*)))
160

    
161
  private[this] def INFO(fmt: String, args: Any*) =
162
    logger.info("UserActor[%s]: %s".format(D_userID, fmt.format(args: _*)))
163

    
164
  private[this] def WARN(fmt: String, args: Any*) =
165
    logger.warn("UserActor[%s]: %s".format(D_userID, fmt.format(args: _*)))
166

    
167
  private[this] def ERROR(fmt: String, args: Any*) =
168
    logger.error("UserActor[%s]: %s".format(D_userID, fmt.format(args: _*)))
169

    
170
  private[this] def ERROR(t: Throwable, fmt: String, args: Any*) =
171
    logger.error("UserActor[%s]: %s".format(D_userID, fmt.format(args: _*)), t)
172
}