Reset failed tasks

This commit is contained in:
simon987 2019-02-27 20:53:09 -05:00
parent 09dd911dc1
commit 67c67090cf
17 changed files with 118 additions and 32 deletions

View File

@ -98,6 +98,7 @@ func New() *WebAPI {
api.router.POST("/project/secret/:id", LogRequestMiddleware(api.SetSecret)) api.router.POST("/project/secret/:id", LogRequestMiddleware(api.SetSecret))
api.router.GET("/project/webhook_secret/:id", LogRequestMiddleware(api.GetWebhookSecret)) api.router.GET("/project/webhook_secret/:id", LogRequestMiddleware(api.GetWebhookSecret))
api.router.POST("/project/webhook_secret/:id", LogRequestMiddleware(api.SetWebhookSecret)) api.router.POST("/project/webhook_secret/:id", LogRequestMiddleware(api.SetWebhookSecret))
api.router.POST("/project/reset_failed_tasks/:id", LogRequestMiddleware(api.ResetFailedTasks))
api.router.POST("/task/submit", LogRequestMiddleware(api.SubmitTask)) api.router.POST("/task/submit", LogRequestMiddleware(api.SubmitTask))
api.router.GET("/task/get/:project", LogRequestMiddleware(api.GetTaskFromProject)) api.router.GET("/task/get/:project", LogRequestMiddleware(api.GetTaskFromProject))

View File

@ -15,7 +15,7 @@ const (
type JsonResponse struct { type JsonResponse struct {
Ok bool `json:"ok"` Ok bool `json:"ok"`
Message string `json:"message,omitempty"` Message string `json:"message,omitempty"`
RateLimitDelay string `json:"rate_limit_delay,omitempty"` RateLimitDelay float64 `json:"rate_limit_delay,omitempty"`
Content interface{} `json:"content,omitempty"` Content interface{} `json:"content,omitempty"`
} }
@ -305,6 +305,11 @@ type GetSecretResponse struct {
type SetWebhookSecretRequest struct { type SetWebhookSecretRequest struct {
WebhookSecret string `json:"webhook_secret"` WebhookSecret string `json:"webhook_secret"`
} }
type GetWebhookSecretResponse struct { type GetWebhookSecretResponse struct {
WebhookSecret string `json:"webhook_secret"` WebhookSecret string `json:"webhook_secret"`
} }
type ResetFailedTaskResponse struct {
AffectedTasks int64 `json:"affected_tasks"`
}

View File

@ -120,7 +120,7 @@ func (api *WebAPI) CreateProject(r *Request) {
} }
api.Database.SetManagerRoleOn(manager.(*storage.Manager).Id, id, api.Database.SetManagerRoleOn(manager.(*storage.Manager).Id, id,
storage.RoleManageAccess|storage.RoleRead|storage.RoleEdit|storage.RoleSecret) storage.RoleManageAccess|storage.RoleRead|storage.RoleEdit|storage.RoleSecret|storage.RoleMaintenance)
r.OkJson(JsonResponse{ r.OkJson(JsonResponse{
Ok: true, Ok: true,
Content: CreateProjectResponse{ Content: CreateProjectResponse{
@ -209,6 +209,9 @@ func (api *WebAPI) UpdateProject(r *Request) {
"project": project, "project": project,
}).Warn("Error during project update") }).Warn("Error during project update")
} else { } else {
api.SubmitLimiters.Delete(project.Id)
api.AssignLimiters.Delete(project.Id)
r.OkJson(JsonResponse{ r.OkJson(JsonResponse{
Ok: true, Ok: true,
}) })
@ -688,3 +691,35 @@ func (api *WebAPI) SetWebhookSecret(r *Request) {
}) })
} }
} }
func (api *WebAPI) ResetFailedTasks(r *Request) {
pid, err := strconv.ParseInt(r.Ctx.UserValue("id").(string), 10, 64)
if err != nil || pid <= 0 {
r.Json(JsonResponse{
Ok: false,
Message: "Invalid project id",
}, 400)
return
}
sess := api.Session.StartFasthttp(r.Ctx)
manager := sess.Get("manager")
if !isActionOnProjectAuthorized(pid, manager, storage.RoleMaintenance, api.Database) {
r.Json(JsonResponse{
Ok: false,
Message: "Unauthorized",
}, 403)
return
}
res := api.Database.ResetFailedTasks(pid)
r.OkJson(JsonResponse{
Ok: true,
Content: ResetFailedTaskResponse{
AffectedTasks: res,
},
})
}

View File

@ -60,7 +60,7 @@ func (api *WebAPI) SubmitTask(r *Request) {
r.Json(JsonResponse{ r.Json(JsonResponse{
Ok: false, Ok: false,
Message: "Too many requests", Message: "Too many requests",
RateLimitDelay: strconv.FormatFloat(delay, 'f', -1, 64), RateLimitDelay: delay,
}, 429) }, 429)
return return
} }
@ -111,7 +111,7 @@ func (api *WebAPI) GetTaskFromProject(r *Request) {
r.Json(JsonResponse{ r.Json(JsonResponse{
Ok: false, Ok: false,
Message: "Too many requests", Message: "Too many requests",
RateLimitDelay: strconv.FormatFloat(delay, 'f', -1, 64), RateLimitDelay: delay,
}, 429) }, 429)
return return
} }

View File

@ -48,7 +48,7 @@ CREATE TABLE task
project INTEGER REFERENCES project (id), project INTEGER REFERENCES project (id),
assignee INTEGER REFERENCES worker (id), assignee INTEGER REFERENCES worker (id),
max_assign_time INTEGER DEFAULT 0, max_assign_time INTEGER DEFAULT 0,
assign_time INTEGER DEFAULT 0, assign_time INTEGER DEFAULT NULL,
verification_count INTEGER DEFAULT 0, verification_count INTEGER DEFAULT 0,
priority SMALLINT DEFAULT 0, priority SMALLINT DEFAULT 0,
retries SMALLINT DEFAULT 0, retries SMALLINT DEFAULT 0,

View File

@ -16,6 +16,7 @@ const (
RoleEdit ManagerRole = 2 RoleEdit ManagerRole = 2
RoleManageAccess ManagerRole = 4 RoleManageAccess ManagerRole = 4
RoleSecret ManagerRole = 8 RoleSecret ManagerRole = 8
RoleMaintenance ManagerRole = 16
) )
type Manager struct { type Manager struct {

13
storage/maintenance.go Normal file
View File

@ -0,0 +1,13 @@
package storage
func (database *Database) ResetFailedTasks(pid int64) int64 {
db := database.getDB()
res, err := db.Exec(`UPDATE task SET status=1, retries=0, assign_time=NULL, assignee=NULL
WHERE project=$1 AND status=2`, pid)
handleErr(err)
rowsAffected, _ := res.RowsAffected()
return rowsAffected
}

View File

@ -48,7 +48,7 @@ CREATE TABLE task
project INTEGER REFERENCES project (id), project INTEGER REFERENCES project (id),
assignee INTEGER REFERENCES worker (id), assignee INTEGER REFERENCES worker (id),
max_assign_time INTEGER DEFAULT 0, max_assign_time INTEGER DEFAULT 0,
assign_time INTEGER DEFAULT 0, assign_time INTEGER DEFAULT NULL,
verification_count INTEGER DEFAULT 0, verification_count INTEGER DEFAULT 0,
priority SMALLINT DEFAULT 0, priority SMALLINT DEFAULT 0,
retries SMALLINT DEFAULT 0, retries SMALLINT DEFAULT 0,

View File

@ -99,19 +99,23 @@ export class ApiService {
} }
getSecret(pid: number) { getSecret(pid: number) {
return this.http.get(this.url + `/project/secret/${pid}`,) return this.http.get(this.url + `/project/secret/${pid}`, this.options)
} }
setSecret(pid: number, secret: string) { setSecret(pid: number, secret: string) {
return this.http.post(this.url + `/project/secret/${pid}`, {"secret": secret}) return this.http.post(this.url + `/project/secret/${pid}`, {"secret": secret}, this.options)
} }
getWebhookSecret(pid: number) { getWebhookSecret(pid: number) {
return this.http.get(this.url + `/project/webhook_secret/${pid}`,) return this.http.get(this.url + `/project/webhook_secret/${pid}`, this.options)
} }
setWebhookSecret(pid: number, secret: string) { setWebhookSecret(pid: number, secret: string) {
return this.http.post(this.url + `/project/webhook_secret/${pid}`, {"webhook_secret": secret}) return this.http.post(this.url + `/project/webhook_secret/${pid}`, {"webhook_secret": secret}, this.options)
}
resetFailedTasks(pid: number) {
return this.http.post(this.url + `/project/reset_failed_tasks/${pid}`, null, this.options)
} }
} }

View File

@ -10,4 +10,6 @@ export interface Project {
chain: number; chain: number;
hidden: boolean; hidden: boolean;
paused: boolean; paused: boolean;
assign_rate: number;
submit_rate: number;
} }

View File

@ -84,7 +84,7 @@
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button mat-raised-button [routerLink]="'/projects'">Back</button> <button mat-raised-button [routerLink]="'../'">{{"nav.back"|translate}}</button>
<button mat-raised-button color="primary" *ngIf="project && auth.logged" <button mat-raised-button color="primary" *ngIf="project && auth.logged"
[routerLink]="'/project/' + project.id + '/update'">{{"project.update" | translate}}</button> [routerLink]="'/project/' + project.id + '/update'">{{"project.update" | translate}}</button>
<button mat-raised-button color="primary" *ngIf="project && auth.logged" <button mat-raised-button color="primary" *ngIf="project && auth.logged"

View File

@ -349,7 +349,16 @@ export class ProjectDashboardComponent implements OnInit {
width: '250px', width: '250px',
}).afterClosed().subscribe(result => { }).afterClosed().subscribe(result => {
if (result) { if (result) {
alert("yes") this.apiService.resetFailedTasks(this.projectId).subscribe(
data => {
this.translate.get("project.reset_response").subscribe(t =>
this.messenger.show(t + data["content"]["affected_tasks"]))
},
error => {
this.translate.get("messenger.unauthorized").subscribe(t =>
this.messenger.show(t))
}
)
} }
}); });
} }

View File

@ -70,7 +70,7 @@
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button mat-raised-button [routerLink]="'../'">Back</button> <button mat-raised-button [routerLink]="'../'">{{"nav.back"|translate}}</button>
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>
</div> </div>

View File

@ -39,7 +39,7 @@
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button mat-raised-button [routerLink]="'../'">Back</button> <button mat-raised-button [routerLink]="'../'">{{"nav.back"|translate}}</button>
<button mat-raised-button color="primary" <button mat-raised-button color="primary"
(click)="onWebhookUpdate()">{{"secret.update" | translate}}</button> (click)="onWebhookUpdate()">{{"secret.update" | translate}}</button>
</mat-card-actions> </mat-card-actions>

View File

@ -38,10 +38,18 @@
<mat-hint align="start">{{'project.git_repo_hint'|translate}}</mat-hint> <mat-hint align="start">{{'project.git_repo_hint'|translate}}</mat-hint>
</mat-form-field> </mat-form-field>
<project-select [(project)]="selectedProject"></project-select> <project-select [(project)]="selectedProject"></project-select>
<mat-form-field appearance="outline">
<mat-label>{{"project.assign_rate"|translate}}</mat-label>
<input matInput [(ngModel)]="project.assign_rate" name="assign_rate" type="number">
</mat-form-field>
<mat-form-field appearance="outline">
<mat-label>{{"project.submit_rate"|translate}}</mat-label>
<input matInput [(ngModel)]="project.submit_rate" name="submit_rate" type="number">
</mat-form-field>
</form> </form>
</mat-card-content> </mat-card-content>
<mat-card-actions> <mat-card-actions>
<button mat-raised-button [routerLink]="'../'">Back</button> <button mat-raised-button [routerLink]="'../'">{{"nav.back"|translate}}</button>
<button type="submit" form="uf" mat-raised-button color="primary">{{"project.update" | translate}}</button> <button type="submit" form="uf" mat-raised-button color="primary">{{"project.update" | translate}}</button>
</mat-card-actions> </mat-card-actions>
</mat-card> </mat-card>

View File

@ -9,7 +9,7 @@
"worker_dashboard": "Workers", "worker_dashboard": "Workers",
"account": "Account", "account": "Account",
"manager_list": "Managers", "manager_list": "Managers",
"back": "back" "back": "Back"
}, },
"logs": { "logs": {
"title": "Logs", "title": "Logs",
@ -69,7 +69,11 @@
"chain": "Chain tasks to", "chain": "Chain tasks to",
"manager_select": "Give access to manager", "manager_select": "Give access to manager",
"version": "Git version (commit hash)", "version": "Git version (commit hash)",
"secret": "Secret" "secret": "Secret",
"reset_response": "Reset failed tasks: ",
"assign_rate": "Task assign rate limit",
"submit_rate": "Task submit rate limit",
"rate": "per second"
}, },
"dashboard": { "dashboard": {
"title": "Dashboard for", "title": "Dashboard for",

View File

@ -9,7 +9,7 @@
"worker_dashboard": "Workers", "worker_dashboard": "Workers",
"account": "Compte", "account": "Compte",
"manager_list": "Managers", "manager_list": "Managers",
"back": "Arrière" "back": "Retour"
}, },
"logs": { "logs": {
"title": "Journaux", "title": "Journaux",
@ -69,7 +69,11 @@
"perms": "Permissions", "perms": "Permissions",
"chain": "Enchainer les tâches vers", "chain": "Enchainer les tâches vers",
"manager_select": "Donner accès à", "manager_select": "Donner accès à",
"version": "Version git (hash du commit)" "version": "Version git (hash du commit)",
"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"
}, },
"dashboard": { "dashboard": {
"title": "Tableau de bord pour ", "title": "Tableau de bord pour ",