Flat project hierarchy
[aquarium] / src / main / scala / gr / grnet / aquarium / user / actor / UserActor.scala
1 /*
2  * Copyright 2011 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.user.actor
37
38 import gr.grnet.aquarium.user.UserState
39 import gr.grnet.aquarium.util.Loggable
40 import gr.grnet.aquarium.processor.actor.{UserResponseGetBalance, UserRequestGetBalance}
41 import scala.PartialFunction
42 import gr.grnet.aquarium.actor._
43 import com.ckkloverdos.maybe.Maybe
44
45
46 /**
47  * 
48  * @author Christos KK Loverdos <loverdos@gmail.com>
49  */
50
51 class UserActor extends AquariumActor with Loggable {
52   @volatile
53   private[this] var _userId: String = _
54   @volatile
55   private[this] var _isInitialized: Boolean = false
56   @volatile
57   private[this] var _userState: UserState = _
58   @volatile
59   private[this] var _actorProvider: ActorProvider = _
60
61   def role = UserActorRole
62
63   protected def receive: Receive = {
64     case UserActorStop ⇒
65       self.stop()
66
67     case m @ UserActorInitWithUserId(userId) ⇒
68       this._userId = userId
69       this._isInitialized = true
70       // TODO: query DB etc to get internal state
71       logger.info("Setup my userId = %s".format(userId))
72
73     case m @ ActorProviderConfigured(actorProvider) ⇒
74       this._actorProvider = actorProvider
75       logger.info("Configured %s with %s".format(this, m))
76
77     case m @ UserRequestGetBalance(userId, timestamp) ⇒
78       if(this._userId != userId) {
79         logger.error("Received %s but my userId = %s".format(m, this._userId))
80         // TODO: throw an exception here
81       } else {
82         // This is the big party.
83         // Get the user state, if it exists and make sure it is not stale.
84
85         // Do we have a user state?
86         if(_userState ne null) {
87           // Yep, we do. See what there is inside it.
88           val credits = _userState.credits
89           val creditsTimestamp = credits.snapshotTime
90
91           // Check if data is stale
92           if(creditsTimestamp + 10000 > timestamp) {
93             // No, it's OK
94             self reply UserResponseGetBalance(userId, credits.data)
95           } else {
96             // Yep, data is stale and must recompute balance
97             // FIXME: implement
98             logger.error("FIXME: Should have computed a new value for %s".format(credits))
99             self reply UserResponseGetBalance(userId, credits.data)
100           }
101         } else {
102           // Nope. No user state exists. Must reproduce one
103           // FIXME: implement
104           logger.error("FIXME: Should have computed the user state for userId = %s".format(userId))
105           self reply UserResponseGetBalance(userId, Maybe(userId.toDouble).getOr(10.5))
106         }
107       }
108   }
109 }