I have an angular service:
getAll(): Observable<Role[]> {
const queryUrl = `${this.baseUrl}/roles/getAll`;
return this.http
.get(queryUrl, this.httpOptions)
.pipe(
map((result: Role[]) => {
return result;
})
);
}
And a Scala API as:
// Controller
def getAll() = Action.async { request =>
println("IN CONTROLLER")
rolesService.getAll().map {
result => {
println("IN CONTROLLER RESULT")
addLog(request.cookies, Roles.GET_ALL)
Ok(Json.toJson(result))
}
}.recover {
case _ => {
println("IN CONTROLLER RECOVER")
InternalServerError
}
}
}
// Service
def getAll(): Future[List[Role]] = {
try {
println("CALL GETALL ROLES IN SERVICE")
val settingsFuture = rolesRepository.getAll
settingsFuture
}
catch {
case e: Exception => Future.failed(e)
}
}
// Repository
def getAll(): Future[List[Role]] = {
// content
// a test method
val startDate = System.currentTimeMillis()
val list = testMillion()
val endDate = System.currentTimeMillis()
println(s"start date ${startDate}, endDate ${endDate}")
}
def testMillion(): List[(Int, String)] = {
println("IN TEST MILLION METHOD")
var roleList: List[(Int, String)] = List.empty
for (i <- 0 to 100000) {
if (i % 10000 == 0) {println(i)}
val row: (Int, String) = (i, getName(i))
roleList = roleList :+ row
}
roleList
}
def getName(i: Int): String = s"Role_${i}"
I created a generic repository and wanted to test it before apply it for all my entities. So, because I use some iterators now, I wanted to test how much time take a simple iteration from 0 to 1 million items with only 2 parameters (Id and Name).
Firstly, I tested with a million of iterations, but my pc failed (my CPU goes to 100% and memory to ~80%). so, downed to one hundred thousand and test again :
Steps : Angular send a request to my api. Controller -> Service -> Repository -> Start iterations. I printed the "i" value at every 10k iterations to watch the progress. For every 10k, this took almost 10 seconds (in my opinion, this time is huge, if we think that is not a db request, just read a number and assign a name which is calculated as "Role_" + i).
Randomly, at 70k/100k (about 60 - 70 seconds from first client request), SURPRISE, is received another request. I thought the method testMillion() is called again because iteration is not finished, but not. The second request came from controller. In this time, Angular service is in waiting status. Ok, first iteration is finished (first request), this send the answer to clientside, but this is not received, because the client is already waiting for the second request. This happening again, second request is not finished and another request is made, until the fourth. But, because the connection is opened from more than 2 minutes, Angular get an error "ERR_CONNECTION_RESET" and the request fail.
I know In Angular Rxjs have an retry() method, but as default I think this is not called. I'm not sure that is 100% clientside fault and resend requests if previous take too much time, but how I see, this is my first think. Or, this issue can be from Scala, because are used futures?
This is just a test, I never had one hundred thousand roles, but for another entity, this can be a real problem. Thanks
LE1: If I set retry(0) in my angular service, the request will fail after 60 seconds. Now, I'm pretty sure that another request are made from client if the previous take too much time. And why initially I had 4 requests? because retry is called 3 times as default, can't understand why, because (from retry definition):
Optional. Default is -1.
Number of retry attempts before failing.
getAll(): Observable<Role[]> {
const queryUrl = `${this.baseUrl}/roles/getAll`;
return this.http
.get(queryUrl, this.httpOptions)
.pipe(
retry(0),
map((result: Role[]) => {
return result;
})
);
}
This is an annoying think. To set for every service method that can took too much time retry(0), or increasing server connection timeout (the last I don't know if is one good solution).
LE2: By the answer of this question, I found that retry is called if timeout is exceeded. But, I don't set a timeout and I know that connection between client and api is about 120 seconds, so, this case can not be possible (I get connection reset after fourth retry, and not timeout connection)