Skip to content

Commit 1d976d3

Browse files
committed
mocking clusters
1 parent 4fd2e09 commit 1d976d3

File tree

6 files changed

+359
-1
lines changed

6 files changed

+359
-1
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* ************************************************************************
2+
3+
osparc - the simcore frontend
4+
5+
https://osparc.io
6+
7+
Copyright:
8+
2025 IT'IS Foundation, https://itis.swiss
9+
10+
License:
11+
MIT: https://opensource.org/licenses/MIT
12+
13+
Authors:
14+
* Odei Maiz (odeimaiz)
15+
16+
************************************************************************ */
17+
18+
19+
qx.Class.define("osparc.jobs.ClustersBrowser", {
20+
extend: qx.ui.core.Widget,
21+
22+
construct() {
23+
this.base(arguments);
24+
25+
this._setLayout(new qx.ui.layout.VBox(10));
26+
27+
this.getChildControl("clusters-table");
28+
},
29+
30+
members: {
31+
_createChildControlImpl: function(id) {
32+
let control;
33+
switch (id) {
34+
case "clusters-table":
35+
control = new osparc.jobs.ClustersTable();
36+
this._add(control);
37+
break;
38+
}
39+
40+
return control || this.base(arguments, id);
41+
},
42+
}
43+
})
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/* ************************************************************************
2+
3+
osparc - the simcore frontend
4+
5+
https://osparc.io
6+
7+
Copyright:
8+
2025 IT'IS Foundation, https://itis.swiss
9+
10+
License:
11+
MIT: https://opensource.org/licenses/MIT
12+
13+
Authors:
14+
* Odei Maiz (odeimaiz)
15+
16+
************************************************************************ */
17+
18+
19+
qx.Class.define("osparc.jobs.ClustersTable", {
20+
extend: qx.ui.table.Table,
21+
22+
construct: function(filters) {
23+
this.base(arguments);
24+
25+
const model = new osparc.jobs.ClustersTableModel(filters);
26+
this.setTableModel(model);
27+
28+
this.set({
29+
statusBarVisible: false,
30+
headerCellHeight: 26,
31+
rowHeight: 26,
32+
});
33+
34+
const columnModel = this.getTableColumnModel();
35+
columnModel.setColumnVisible(this.self().COLS.CLUSTER_ID.column, false);
36+
},
37+
38+
statics: {
39+
COLS: {
40+
CLUSTER_ID: {
41+
id: "clusterId",
42+
column: 0,
43+
label: qx.locale.Manager.tr("Cluster Id"),
44+
width: 170
45+
},
46+
NAME: {
47+
id: "name",
48+
column: 1,
49+
label: qx.locale.Manager.tr("Name"),
50+
width: 100
51+
},
52+
STATUS: {
53+
id: "status",
54+
column: 2,
55+
label: qx.locale.Manager.tr("Status"),
56+
width: 170
57+
},
58+
N_WORKERS: {
59+
id: "nWorkers",
60+
column: 3,
61+
label: qx.locale.Manager.tr("# Workers"),
62+
width: 80
63+
},
64+
}
65+
},
66+
});
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
/* ************************************************************************
2+
3+
osparc - the simcore frontend
4+
5+
https://osparc.io
6+
7+
Copyright:
8+
2025 IT'IS Foundation, https://itis.swiss
9+
10+
License:
11+
MIT: https://opensource.org/licenses/MIT
12+
13+
Authors:
14+
* Odei Maiz (odeimaiz)
15+
16+
************************************************************************ */
17+
18+
19+
qx.Class.define("osparc.jobs.ClustersTableModel", {
20+
extend: qx.ui.table.model.Remote,
21+
22+
construct(filters) {
23+
this.base(arguments);
24+
25+
const clustersCols = osparc.jobs.ClustersTable.COLS;
26+
const colLabels = Object.values(clustersCols).map(col => col.label);
27+
const colIDs = Object.values(clustersCols).map(col => col.id);
28+
this.setColumns(colLabels, colIDs);
29+
30+
if (filters) {
31+
this.setFilters(filters);
32+
}
33+
34+
this.setSortAscendingWithoutSortingData(false);
35+
this.setColumnSortable(clustersCols.CLUSTER_ID.column, false);
36+
this.setColumnSortable(clustersCols.N_WORKERS.column, false);
37+
},
38+
39+
properties: {
40+
isFetching: {
41+
check: "Boolean",
42+
init: false,
43+
event: "changeFetching"
44+
},
45+
46+
filters: {
47+
check: "Object",
48+
init: null,
49+
apply: "reloadData", // force reload
50+
},
51+
52+
orderBy: {
53+
check: "Object",
54+
init: {
55+
field: "name",
56+
direction: "asc"
57+
}
58+
},
59+
},
60+
61+
statics: {
62+
SERVER_MAX_LIMIT: 49,
63+
},
64+
65+
members: {
66+
// overridden
67+
_loadRowCount() {
68+
const urlParams = {
69+
offset: 0,
70+
limit: 1,
71+
filters: this.getFilters() ?
72+
JSON.stringify({
73+
"started_at": this.getFilters()
74+
}) :
75+
null,
76+
orderBy: JSON.stringify(this.getOrderBy()),
77+
};
78+
const options = {
79+
resolveWResponse: true
80+
};
81+
osparc.store.Clusters.getInstance().fetchClusters(urlParams, options)
82+
.then(clusters => {
83+
this._onRowCountLoaded(clusters.length);
84+
})
85+
.catch(() => this._onRowCountLoaded(null));
86+
},
87+
88+
// overridden
89+
_loadRowData(firstRow, qxLastRow) {
90+
this.setIsFetching(true);
91+
92+
const lastRow = Math.min(qxLastRow, this._rowCount - 1);
93+
// Returns a request promise with given offset and limit
94+
const getFetchPromise = (offset, limit=this.self().SERVER_MAX_LIMIT) => {
95+
const urlParams = {
96+
limit,
97+
offset,
98+
filters: this.getFilters() ?
99+
JSON.stringify({
100+
"started_at": this.getFilters()
101+
}) :
102+
null,
103+
orderBy: JSON.stringify(this.getOrderBy())
104+
};
105+
return osparc.store.Clusters.getInstance().fetchClusters(urlParams)
106+
.then(clusters => {
107+
const data = [];
108+
const jobsCols = osparc.jobs.JobsTable.COLS;
109+
clusters.forEach(cluster => {
110+
data.push({
111+
[jobsCols.CLUSTER_ID.id]: cluster.getClusterId(),
112+
[jobsCols.NAME.id]: cluster.getName(),
113+
[jobsCols.STATUS.id]: cluster.getStatus(),
114+
[jobsCols.N_WORKERS.id]: cluster.getNWorkers() ? cluster.getNWorkers() : 0,
115+
});
116+
});
117+
return data;
118+
});
119+
};
120+
121+
// Divides the model row request into several server requests to comply with the number of rows server limit
122+
const reqLimit = lastRow - firstRow + 1; // Number of requested rows
123+
const nRequests = Math.ceil(reqLimit / this.self().SERVER_MAX_LIMIT);
124+
if (nRequests > 1) {
125+
const requests = [];
126+
for (let i=firstRow; i <= lastRow; i += this.self().SERVER_MAX_LIMIT) {
127+
requests.push(getFetchPromise(i, i > lastRow - this.self().SERVER_MAX_LIMIT + 1 ? reqLimit % this.self().SERVER_MAX_LIMIT : this.self().SERVER_MAX_LIMIT))
128+
}
129+
Promise.all(requests)
130+
.then(responses => this._onRowDataLoaded(responses.flat()))
131+
.catch(err => {
132+
console.error(err);
133+
this._onRowDataLoaded(null);
134+
})
135+
.finally(() => this.setIsFetching(false));
136+
} else {
137+
getFetchPromise(firstRow, reqLimit)
138+
.then(data => {
139+
this._onRowDataLoaded(data);
140+
})
141+
.catch(err => {
142+
console.error(err)
143+
this._onRowDataLoaded(null);
144+
})
145+
.finally(() => this.setIsFetching(false));
146+
}
147+
}
148+
}
149+
})

services/static-webserver/client/source/class/osparc/jobs/JobsAndClusters.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ qx.Class.define("osparc.jobs.JobsAndClusters", {
3939
const clustersPage = new qx.ui.tabview.Page(this.tr("Clusters")).set({
4040
layout: new qx.ui.layout.VBox(10)
4141
});
42-
const clustersBrowser = new osparc.jobs.JobsBrowser();
42+
const clustersBrowser = new osparc.jobs.ClustersBrowser();
4343
const scroller2 = new qx.ui.container.Scroll();
4444
scroller2.add(clustersBrowser);
4545
clustersPage.add(scroller2);
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/* ************************************************************************
2+
3+
osparc - the simcore frontend
4+
5+
https://osparc.io
6+
7+
Copyright:
8+
2025 IT'IS Foundation, https://itis.swiss
9+
10+
License:
11+
MIT: https://opensource.org/licenses/MIT
12+
13+
Authors:
14+
* Odei Maiz (odeimaiz)
15+
16+
************************************************************************ */
17+
18+
/**
19+
* @asset(osparc/mock_clusters.json")
20+
*/
21+
22+
qx.Class.define("osparc.store.Clusters", {
23+
extend: qx.core.Object,
24+
type: "singleton",
25+
26+
properties: {
27+
clusters: {
28+
check: "Array",
29+
init: [],
30+
nullable: true,
31+
event: "changeClusters"
32+
}
33+
},
34+
35+
members: {
36+
fetchClusters: function() {
37+
return osparc.utils.Utils.fetchJSON("/resource/osparc/mock_clusters.json")
38+
.then(clustersData => {
39+
if ("clusters" in clustersData) {
40+
clustersData["clusters"].forEach(jobData => {
41+
this.addJob(jobData);
42+
});
43+
}
44+
return this.getClusters();
45+
})
46+
.catch(err => console.error(err));
47+
},
48+
49+
addJob: function(jobData) {
50+
const clusters = this.getClusters();
51+
const index = clusters.findIndex(t => t.getJobId() === jobData["job_id"]);
52+
if (index === -1) {
53+
const job = new osparc.data.Job(jobData);
54+
clusters.push(job);
55+
this.fireDataEvent("changeClusters");
56+
return job;
57+
}
58+
return null;
59+
},
60+
61+
removeClusters: function() {
62+
const clusters = this.getClusters();
63+
clusters.forEach(job => job.dispose());
64+
this.fireDataEvent("changeClusters");
65+
},
66+
}
67+
});
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"clusters": [{
3+
"job_id": "0cde4607-07de-4bb5-b3e6-487f22387a70",
4+
"name": "cluster_1",
5+
"status": "RUNNING",
6+
"nWorkers": 2
7+
}, {
8+
"job_id": "5685a699-4927-479e-9b34-e5ab1616303a",
9+
"name": "cluster_2",
10+
"status": "WAITING FOR RESOURCES",
11+
"nWorkers": 4
12+
}, {
13+
"job_id": "a8ca6a02-8816-48a6-8c6b-b94b3e431c8c",
14+
"name": "cluster_3",
15+
"status": "PENDING",
16+
"nWorkers": 8
17+
}, {
18+
"job_id": "a8ca6a02-8816-48a6-8c6b-b94b3e431c8d",
19+
"name": "cluster_4",
20+
"status": "ERROR",
21+
"nWorkers": 12
22+
}, {
23+
"job_id": "a8ca6a02-8816-48a6-8c6b-b94b3e431c81",
24+
"name": "cluster_5",
25+
"status": "IDK",
26+
"nWorkers": 24
27+
}, {
28+
"job_id": "a8ca6a02-8816-48a6-8c6b-b94b3e431c82",
29+
"name": "cluster_6",
30+
"status": "SOMETHING_ELSE",
31+
"nWorkers": 42
32+
}]
33+
}

0 commit comments

Comments
 (0)