mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-23 16:00:38 +00:00
add proper jobs timings for raw apps
This commit is contained in:
+5
-5
@@ -46,11 +46,11 @@
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
true,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
false,
|
||||
true,
|
||||
true
|
||||
]
|
||||
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "SELECT\n j.created_at AS \"created_at!\",\n c.started_at,\n c.duration_ms,\n j.created_by AS \"created_by!\"\n FROM v2_job_completed c\n JOIN v2_job j USING (id)\n WHERE c.id = $1 AND c.workspace_id = $2 AND ($3::text[] IS NULL OR j.tag = ANY($3))",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
"ordinal": 0,
|
||||
"name": "created_at!",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 1,
|
||||
"name": "started_at",
|
||||
"type_info": "Timestamptz"
|
||||
},
|
||||
{
|
||||
"ordinal": 2,
|
||||
"name": "duration_ms",
|
||||
"type_info": "Int8"
|
||||
},
|
||||
{
|
||||
"ordinal": 3,
|
||||
"name": "created_by!",
|
||||
"type_info": "Varchar"
|
||||
}
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Uuid",
|
||||
"Text",
|
||||
"TextArray"
|
||||
]
|
||||
},
|
||||
"nullable": [
|
||||
false,
|
||||
true,
|
||||
false,
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "73d1019fdff3113fb0c561048273ba57bf2364adebb895eba57896895b96f8d4"
|
||||
}
|
||||
+2
-2
@@ -18,8 +18,8 @@
|
||||
"Left": []
|
||||
},
|
||||
"nullable": [
|
||||
true,
|
||||
false
|
||||
false,
|
||||
true
|
||||
]
|
||||
},
|
||||
"hash": "b3dbdfb50ee8118bdaed3164b210cb549a34b96554ae1872355b90304f5dcb76"
|
||||
|
||||
+1
-3
@@ -59,9 +59,7 @@
|
||||
"failure",
|
||||
"command",
|
||||
"approval",
|
||||
"preprocessor",
|
||||
"schedule_handler_old",
|
||||
"dynamic_skip"
|
||||
"preprocessor"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9717,6 +9717,34 @@ paths:
|
||||
- completed
|
||||
- result
|
||||
|
||||
/w/{workspace}/jobs_u/completed/get_timing/{id}:
|
||||
get:
|
||||
summary: get completed job timing
|
||||
operationId: getCompletedJobTiming
|
||||
tags:
|
||||
- job
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- $ref: "#/components/parameters/JobId"
|
||||
responses:
|
||||
"200":
|
||||
description: job timing details
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
started_at:
|
||||
type: string
|
||||
format: date-time
|
||||
duration_ms:
|
||||
type: integer
|
||||
required:
|
||||
- created_at
|
||||
|
||||
/w/{workspace}/jobs/completed/delete/{id}:
|
||||
post:
|
||||
summary: delete completed job (erase content but keep run id)
|
||||
|
||||
@@ -301,6 +301,10 @@ pub fn workspaced_service() -> Router {
|
||||
"/completed/get_result_maybe/:id",
|
||||
get(get_completed_job_result_maybe).layer(cors.clone()),
|
||||
)
|
||||
.route(
|
||||
"/completed/get_timing/:id",
|
||||
get(get_completed_job_timing).layer(cors.clone()),
|
||||
)
|
||||
.route(
|
||||
"/completed/delete/:id",
|
||||
post(delete_completed_job).layer(cors.clone()),
|
||||
@@ -377,6 +381,7 @@ pub fn workspace_unauthed_service() -> Router {
|
||||
"/completed/get_result_maybe/:id",
|
||||
get(get_completed_job_result_maybe),
|
||||
)
|
||||
.route("/completed/get_timing/:id", get(get_completed_job_timing))
|
||||
.route("/getupdate/:id", get(get_job_update))
|
||||
.route("/getupdate_sse/:id", get(get_job_update_sse))
|
||||
.route("/get_log_file/*file_path", get(get_log_file))
|
||||
@@ -8561,6 +8566,54 @@ async fn get_completed_job_result_maybe(
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct JobTiming {
|
||||
created_at: chrono::DateTime<Utc>,
|
||||
started_at: Option<chrono::DateTime<Utc>>,
|
||||
duration_ms: Option<i64>,
|
||||
}
|
||||
|
||||
async fn get_completed_job_timing(
|
||||
OptAuthed(opt_authed): OptAuthed,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, id)): Path<(String, Uuid)>,
|
||||
) -> error::JsonResult<JobTiming> {
|
||||
let tags = opt_authed
|
||||
.as_ref()
|
||||
.map(|authed| get_scope_tags(authed))
|
||||
.flatten();
|
||||
|
||||
let result = sqlx::query!(
|
||||
"SELECT
|
||||
j.created_at AS \"created_at!\",
|
||||
c.started_at,
|
||||
c.duration_ms,
|
||||
j.created_by AS \"created_by!\"
|
||||
FROM v2_job_completed c
|
||||
JOIN v2_job j USING (id)
|
||||
WHERE c.id = $1 AND c.workspace_id = $2 AND ($3::text[] IS NULL OR j.tag = ANY($3))",
|
||||
id,
|
||||
&w_id,
|
||||
tags.as_ref().map(|v| v.as_slice()) as Option<&[&str]>,
|
||||
)
|
||||
.fetch_optional(&db)
|
||||
.await?;
|
||||
|
||||
let result = not_found_if_none(result, "Completed Job", id.to_string())?;
|
||||
|
||||
if opt_authed.is_none() && result.created_by != "anonymous" {
|
||||
return Err(Error::BadRequest(
|
||||
"As a non logged in user, you can only see jobs ran by anonymous users".to_string(),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Json(JobTiming {
|
||||
created_at: result.created_at,
|
||||
started_at: result.started_at,
|
||||
duration_ms: Some(result.duration_ms),
|
||||
}))
|
||||
}
|
||||
|
||||
async fn delete_completed_job<'a>(
|
||||
authed: ApiAuthed,
|
||||
Tokened { token }: Tokened,
|
||||
|
||||
@@ -11,12 +11,11 @@
|
||||
import Badge from '$lib/components/common/badge/Badge.svelte'
|
||||
|
||||
import YAML from 'yaml'
|
||||
import Tooltip from '../Tooltip.svelte'
|
||||
|
||||
let drawer: Drawer | undefined = undefined
|
||||
let pendingRaw: string = ''
|
||||
let pendingRaw: string = $state('')
|
||||
|
||||
let importType: 'yaml' | 'json' = 'yaml'
|
||||
let importType: 'yaml' | 'json' = $state('yaml')
|
||||
|
||||
// Modal states
|
||||
let appTypeModalOpen = $state(false)
|
||||
|
||||
@@ -46,6 +46,21 @@
|
||||
if (event.data.type == 'backend') {
|
||||
respond({ result, error })
|
||||
}
|
||||
if (editor) {
|
||||
try {
|
||||
let jobInfo = await JobService.getCompletedJobTiming({ workspace, id: uuid })
|
||||
if (jobInfo.started_at) {
|
||||
jobsById[uuid] = {
|
||||
...(jobsById[uuid] ?? {}),
|
||||
created_at: new Date(jobInfo.created_at).getTime(),
|
||||
started_at: new Date(jobInfo.started_at).getTime(),
|
||||
duration_ms: jobInfo.duration_ms
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Error getting job info', e)
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
if (event.data.type == 'backend' || event.data.type == 'backendAsync') {
|
||||
@@ -100,7 +115,7 @@
|
||||
} else if (event.data.type == 'waitJob') {
|
||||
await respondWithResult(data.jobId)
|
||||
} else if (event.data.type == 'getJob') {
|
||||
const job = JobService.getJob({ workspace, id: data.jobId })
|
||||
const job = await JobService.getJob({ workspace, id: data.jobId })
|
||||
respond({ result: job })
|
||||
} else {
|
||||
console.error('No runnable found for', runnable_id)
|
||||
|
||||
Reference in New Issue
Block a user