1
1
package de .upb .cs .swt .delphi .instanceregistry
2
2
3
- import java .util .concurrent .TimeUnit
4
3
5
4
import akka .actor .ActorSystem
6
5
import akka .http .scaladsl .server
7
6
import akka .http .scaladsl .model .{HttpResponse , StatusCodes }
8
7
import akka .http .scaladsl .server .HttpApp
9
- import akka .http .scaladsl .unmarshalling .Unmarshal
10
8
import akka .stream .ActorMaterializer
11
- import akka .util .Timeout
12
9
import de .upb .cs .swt .delphi .instanceregistry .io .swagger .client .model .InstanceEnums .ComponentType
13
10
import io .swagger .client .model .{Instance , JsonSupport }
14
11
15
- import scala .collection .mutable
16
- import scala .concurrent .{Await , ExecutionContext }
17
- import scala .concurrent .duration .Duration
12
+ import scala .concurrent .ExecutionContext
13
+ import spray .json ._
14
+
15
+ import scala .util .{Failure , Success }
18
16
19
17
20
18
/**
21
19
* Web server configuration for Instance Registry API.
22
20
*/
23
21
object Server extends HttpApp with JsonSupport with AppLogging {
24
22
25
- // Default ES instance for testing
26
- private val instances = mutable.HashSet (Instance (Some (0 ), " elasticsearch://localhost" , 9200 , " Default ElasticSearch Instance" , ComponentType .ElasticSearch ))
27
-
28
- implicit val system : ActorSystem = ActorSystem (" delphi-registry" )
23
+ implicit val system : ActorSystem = Registry .system
29
24
implicit val materializer : ActorMaterializer = ActorMaterializer ()
30
25
implicit val ec : ExecutionContext = system.dispatcher
31
- implicit val timeout : Timeout = Timeout (5 , TimeUnit .SECONDS )
26
+
27
+ private val handler : RequestHandler = Registry .requestHandler
32
28
33
29
override def routes : server.Route =
34
30
path(" register" ) {entity(as[String ]) { jsonString => addInstance(jsonString) }} ~
@@ -43,106 +39,102 @@ object Server extends HttpApp with JsonSupport with AppLogging {
43
39
post
44
40
{
45
41
log.debug(s " POST /register has been called, parameter is: $InstanceString" )
46
- Await .result(Unmarshal (InstanceString ).to[Instance ] map {paramInstance =>
47
- val name = paramInstance.name
48
- val newID : Long = {
49
- if (instances.isEmpty){
50
- 0L
51
- }
52
- else {
53
- (instances map( instance => instance.id.get) max) + 1L
54
- }
55
- }
56
42
57
- val instanceToRegister = Instance (id = Some (newID), host = paramInstance.host, portNumber = paramInstance.portNumber, name = paramInstance.name, componentType = paramInstance.componentType)
58
-
59
- instances += instanceToRegister
60
- log.info(s " Instance with name $name registered, ID $newID assigned. " )
61
-
62
- complete {newID.toString()}
63
- } recover {case ex =>
64
- log.warning(s " Failed to read registering instance, exception: $ex" )
65
- complete(HttpResponse (StatusCodes .InternalServerError , entity = " Failed to unmarshal parameter." ))
66
- }, Duration .Inf )
43
+ try {
44
+ val paramInstance : Instance = InstanceString .parseJson.convertTo[Instance ](instanceFormat)
45
+ handler.registerNewInstance(paramInstance) match {
46
+ case Success (id) => complete{id.toString}
47
+ case Failure (_) => complete(HttpResponse (StatusCodes .InternalServerError , entity = " An internal server error occurred." ))
48
+ }
49
+ } catch {
50
+ case dx : DeserializationException =>
51
+ log.error(dx, " Deserialization exception" )
52
+ complete(HttpResponse (StatusCodes .BadRequest , entity = s " Could not deserialize parameter instance with message ${dx.getMessage}. " ))
53
+ case _ : Exception => complete(HttpResponse (StatusCodes .InternalServerError , entity = " An internal server error occurred." ))
54
+ }
67
55
}
68
56
}
69
57
70
58
def deleteInstance () : server.Route = parameters(' Id .as[Long ]){ Id =>
71
59
post {
72
60
log.debug(s " POST /deregister?Id= $Id has been called " )
73
61
74
- val instanceToRemove = instances find(instance => instance.id.get == Id )
75
-
76
- if (instanceToRemove.isEmpty){
77
- log.warning(s " Cannot remove instance with id $Id, that id is not present on the server " )
78
- complete{HttpResponse (StatusCodes .NotFound , entity = s " Id $Id not present on the server " )}
79
- }
80
- else {
81
- instances remove instanceToRemove.get
82
- log.info(s " Successfully removed instance with id $Id" )
83
- complete {s " Successfully removed instance with id $Id" }
62
+ handler.removeInstance(Id ) match {
63
+ case Success (_) =>
64
+ log.info(s " Successfully removed instance with id $Id" )
65
+ complete {s " Successfully removed instance with id $Id" }
66
+ case Failure (x) =>
67
+ log.error(x, s " Cannot remove instance with id $Id, that id is not known to the server. " )
68
+ complete{HttpResponse (StatusCodes .NotFound , entity = s " Id $Id not known to the server " )}
84
69
}
85
70
}
86
71
}
72
+
87
73
def fetchInstancesOfType () : server.Route = parameters(' ComponentType .as[String ]) { compTypeString =>
88
74
get {
89
75
log.debug(s " GET /instances?ComponentType= $compTypeString has been called " )
76
+
90
77
val compType : ComponentType = ComponentType .values.find(v => v.toString == compTypeString).orNull
91
- val matchingInstancesList = List () ++ instances filter {instance => instance.componentType == compType}
92
78
93
- complete {matchingInstancesList}
79
+ if (compType != null ) {
80
+ complete{handler.getAllInstancesOfType(compType)}
81
+ } else {
82
+ log.error(s " Failed to deserialize parameter string $compTypeString to ComponentType. " )
83
+ complete(HttpResponse (StatusCodes .BadRequest , entity = s " Could not deserialize parameter string $compTypeString to ComponentType " ))
84
+ }
94
85
}
95
86
}
96
87
97
88
def numberOfInstances () : server.Route = parameters(' ComponentType .as[String ]) { compTypeString =>
98
89
get {
99
90
log.debug(s " GET /numberOfInstances?ComponentType= $compTypeString has been called " )
100
91
val compType : ComponentType = ComponentType .values.find(v => v.toString == compTypeString).orNull
101
- val count : Int = instances count {instance => instance.componentType == compType}
102
- complete{count.toString()}
92
+
93
+ if (compType != null ) {
94
+ complete{handler.getNumberOfInstances(compType).toString()}
95
+ } else {
96
+ log.error(s " Failed to deserialize parameter string $compTypeString to ComponentType. " )
97
+ complete(HttpResponse (StatusCodes .BadRequest , entity = s " Could not deserialize parameter string $compTypeString to ComponentType " ))
98
+ }
103
99
}
104
100
}
105
101
106
102
def getMatchingInstance () : server.Route = parameters(' ComponentType .as[String ]){ compTypeString =>
107
103
get{
108
104
log.debug(s " GET /matchingInstance?ComponentType= $compTypeString has been called " )
105
+
109
106
val compType : ComponentType = ComponentType .values.find(v => v.toString == compTypeString).orNull
110
107
log.info(s " Looking for instance of type $compType ... " )
111
- val matchingInstances = instances filter {instance => instance.componentType == compType}
112
- if (matchingInstances.isEmpty){
113
- log.warning(s " Could not find matching instance for type $compType . " )
114
- complete(HttpResponse (StatusCodes .NotFound , entity = s " Could not find matching instance for type $compType" ))
115
- }
116
- else {
117
- val matchedInstance = matchingInstances.iterator.next()
118
- log.info(s " Matched to $matchedInstance. " )
119
- complete(matchedInstance)
120
- }
121
108
109
+ if (compType != null ){
110
+ handler.getMatchingInstanceOfType(compType) match {
111
+ case Success (matchedInstance) =>
112
+ log.info(s " Matched to $matchedInstance. " )
113
+ complete(matchedInstance)
114
+ case Failure (x) =>
115
+ log.warning(s " Could not find matching instance for type $compType, message was ${x.getMessage}. " )
116
+ complete(HttpResponse (StatusCodes .NotFound , entity = s " Could not find matching instance for type $compType" ))
117
+ }
118
+ } else {
119
+ log.error(s " Failed to deserialize parameter string $compTypeString to ComponentType. " )
120
+ complete(HttpResponse (StatusCodes .BadRequest , entity = s " Could not deserialize parameter string $compTypeString to ComponentType " ))
121
+ }
122
122
}
123
123
}
124
124
125
- def matchInstance () : server.Route = parameters(' Id .as[Long ], ' MatchingSuccessful .as[Boolean ]){ (Id , MatchingResult ) =>
125
+ def matchInstance () : server.Route = parameters(' Id .as[Long ], ' MatchingSuccessful .as[Boolean ]){ (id, matchingResult ) =>
126
126
post {
127
- // TODO: Need to keep track of matching, maybe remove instances if not reachable!
128
- log.debug( s " POST /matchingResult?Id= $Id &MatchingSuccessful= $MatchingResult has been called " )
129
- if ( MatchingResult ) {
130
- log.info( s " Instance with Id $Id was successfully matched. " )
131
- }
132
- else {
133
- log.warning( s " A client was not able to reach matched instance with Id $Id ! " )
127
+ log.debug( s " POST /matchingResult?Id= $id &MatchingSuccessful= $matchingResult has been called " )
128
+
129
+ handler.applyMatchingResult(id, matchingResult) match {
130
+ case Success (_) => complete{ s " Matching result $matchingResult processed. " }
131
+ case Failure (x) =>
132
+ log.warning( s " Could not process matching result, exception was: ${x.getMessage} " )
133
+ complete( HttpResponse ( StatusCodes . NotFound , entity = s " Could not process matching result, id $id was not found. " ) )
134
134
}
135
- complete {s " Matching result $MatchingResult processed. " }
136
135
}
137
136
}
138
137
139
- def main (args : Array [String ]): Unit = {
140
- val configuration = new Configuration ()
141
- Server .startServer(configuration.bindHost, configuration.bindPort)
142
- system.terminate()
143
- }
144
-
145
-
146
138
}
147
139
148
140
0 commit comments