diff --git a/frontend/src/pages/workers.vue b/frontend/src/pages/workers.vue
index 563c643..fbd19c1 100644
--- a/frontend/src/pages/workers.vue
+++ b/frontend/src/pages/workers.vue
@@ -1,5 +1,20 @@
- TODO
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/server/src/github.rs b/server/src/github.rs
index 545167e..01a0854 100644
--- a/server/src/github.rs
+++ b/server/src/github.rs
@@ -2,7 +2,6 @@ use crate::ARGS;
use octocrab::models::pulls::PullRequest;
use octocrab::{models::InstallationId, Octocrab};
use serde::{Deserialize, Serialize};
-use teloxide::prelude::*;
use teloxide::types::{ChatId, Message};
#[derive(Deserialize, Serialize, Debug)]
diff --git a/server/src/main.rs b/server/src/main.rs
index ac1830d..a6153b7 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -8,7 +8,8 @@ use diesel::r2d2::Pool;
use server::bot::{answer, Command};
use server::recycler::recycler_worker;
use server::routes::{
- dashboard_status, ping, job_list, pipeline_list, pipeline_new_pr, worker_job_update, worker_poll, AppState
+ dashboard_status, job_list, ping, pipeline_list, pipeline_new_pr, worker_job_update,
+ worker_list, worker_poll, AppState,
};
use server::routes::{pipeline_new, worker_heartbeat};
use server::routes::{pipeline_status, worker_status};
@@ -70,6 +71,7 @@ async fn main() -> anyhow::Result<()> {
.route("/api/worker/poll", post(worker_poll))
.route("/api/worker/job_update", post(worker_job_update))
.route("/api/worker/status", get(worker_status))
+ .route("/api/worker/list", get(worker_list))
.route("/api/dashboard/status", get(dashboard_status))
.fallback_service(serve_dir)
.with_state(state)
diff --git a/server/src/routes.rs b/server/src/routes.rs
index a121c87..c252834 100644
--- a/server/src/routes.rs
+++ b/server/src/routes.rs
@@ -869,3 +869,66 @@ pub async fn job_list(
})?,
))
}
+
+#[derive(Deserialize)]
+pub struct WorkerListRequest {
+ page: i64,
+ items_per_page: i64,
+}
+
+#[derive(Serialize)]
+pub struct WorkerListResponseItem {
+ id: i32,
+ hostname: String,
+ arch: String,
+ logical_cores: i32,
+ memory_bytes: i64,
+}
+
+#[derive(Serialize)]
+pub struct WorkerListResponse {
+ total_items: i64,
+ items: Vec,
+}
+
+pub async fn worker_list(
+ Query(query): Query,
+ State(AppState { pool, .. }): State,
+) -> Result, AnyhowError> {
+ let mut conn = pool
+ .get()
+ .context("Failed to get db connection from pool")?;
+
+ Ok(Json(
+ conn.transaction::(|conn| {
+ let total_items = crate::schema::workers::dsl::workers
+ .count()
+ .get_result(conn)?;
+
+ let workers = if query.items_per_page == -1 {
+ crate::schema::workers::dsl::workers
+ .order_by(crate::schema::workers::dsl::id)
+ .load::(conn)?
+ } else {
+ crate::schema::workers::dsl::workers
+ .order_by(crate::schema::workers::dsl::id)
+ .offset((query.page - 1) * query.items_per_page)
+ .limit(query.items_per_page)
+ .load::(conn)?
+ };
+
+ let mut items = vec![];
+ for worker in workers {
+ items.push(WorkerListResponseItem {
+ id: worker.id,
+ hostname: worker.hostname,
+ arch: worker.arch,
+ logical_cores: worker.logical_cores,
+ memory_bytes: worker.memory_bytes,
+ });
+ }
+
+ Ok(WorkerListResponse { total_items, items })
+ })?,
+ ))
+}