diff --git a/api/task.go b/api/task.go
index 8a35f5f..f01cea6 100644
--- a/api/task.go
+++ b/api/task.go
@@ -63,6 +63,7 @@ func (api *WebAPI) SubmitTask(r *Request) {
Message: "Too many requests",
RateLimitDelay: delay,
}, 429)
+ reservation.Cancel()
return
}
@@ -114,6 +115,7 @@ func (api *WebAPI) GetTaskFromProject(r *Request) {
Message: "Too many requests",
RateLimitDelay: delay,
}, 429)
+ reservation.Cancel()
return
}
diff --git a/web/angular/src/app/project-dashboard/project-dashboard.component.html b/web/angular/src/app/project-dashboard/project-dashboard.component.html
index d54dc5f..e13b181 100644
--- a/web/angular/src/app/project-dashboard/project-dashboard.component.html
+++ b/web/angular/src/app/project-dashboard/project-dashboard.component.html
@@ -18,6 +18,10 @@
{{"project.motd" | translate}}:
{{project.motd}}
+ {{"project.task_per_second" | translate}}:
+ {{avgTask | number}}/s
+
+
diff --git a/web/angular/src/app/project-dashboard/project-dashboard.component.ts b/web/angular/src/app/project-dashboard/project-dashboard.component.ts
index 2192e7c..2137dce 100644
--- a/web/angular/src/app/project-dashboard/project-dashboard.component.ts
+++ b/web/angular/src/app/project-dashboard/project-dashboard.component.ts
@@ -26,6 +26,7 @@ export class ProjectDashboardComponent implements OnInit {
private timeline: Chart;
private statusPie: Chart;
private assigneesPie: Chart;
+ private avgTask: number;
private colors = {
@@ -336,6 +337,8 @@ export class ProjectDashboardComponent implements OnInit {
this.assignees = data.content.assignees;
this.setupAssigneesPie();
});
+
+ this.averageTaskPerSecond();
})
},
error => {
@@ -371,6 +374,27 @@ export class ProjectDashboardComponent implements OnInit {
this.setPaused(false)
}
+ private averageTaskPerSecond() {
+
+ const averageDelta = ([x, ...xs]) => {
+ if (x === undefined)
+ return NaN;
+ else
+ return xs.reduce(
+ ([acc, last], x) => [acc + (x - last), x],
+ [0, x]
+ ) [0] / xs.length
+ };
+
+ let interval = this.snapshots.length > 1 ? this.snapshots[0].time_stamp - this.snapshots[1].time_stamp : 0;
+
+ if (interval != 0) {
+ this.avgTask = averageDelta(this.snapshots.reverse().map(s => s.closed_task_count) as any) / interval;
+ } else {
+ return 0
+ }
+ }
+
private setPaused(paused: boolean) {
this.dialog.open(AreYouSureComponent, {
width: '250px',
diff --git a/web/angular/src/assets/i18n/en.json b/web/angular/src/assets/i18n/en.json
index 4e8ad98..0cd1c47 100644
--- a/web/angular/src/assets/i18n/en.json
+++ b/web/angular/src/assets/i18n/en.json
@@ -73,7 +73,8 @@
"reset_response": "Reset failed tasks: ",
"assign_rate": "Task assign rate limit",
"submit_rate": "Task submit rate limit",
- "rate": "per second"
+ "rate": "per second",
+ "task_per_second": "Completed tasks per second"
},
"dashboard": {
"title": "Dashboard for",
diff --git a/web/angular/src/assets/i18n/fr.json b/web/angular/src/assets/i18n/fr.json
index cef1007..008d052 100644
--- a/web/angular/src/assets/i18n/fr.json
+++ b/web/angular/src/assets/i18n/fr.json
@@ -73,7 +73,8 @@
"reset_response": "Réinitialisé les tâches en échec: ",
"assign_rate": "Taux d'assignation de tâches",
"submit_rate": "Taux de soumission de tâches",
- "rate": "par seconde"
+ "rate": "par seconde",
+ "task_per_second": "Tâches par seconde"
},
"dashboard": {
"title": "Tableau de bord pour ",