Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show wk user in vx workflow list and enable cache busting for bundle chunks #7854

Merged
merged 44 commits into from
Jun 6, 2024
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
d17c9b2
try to adjust backend by passing through the wk user id
dieknolle3333 May 8, 2024
9239245
WIP [ci skip] start to show wk user
dieknolle3333 May 8, 2024
fda5743
join with webknossos.user_ table to get user first and lastname
dieknolle3333 May 12, 2024
13c2f39
remove wk user id
dieknolle3333 May 12, 2024
4488e31
show merged username and have host name as backup
dieknolle3333 May 15, 2024
ff1bc0b
Merge branch 'master' into show-wk-user-in-vx-workflow-list
dieknolle3333 May 16, 2024
ced9106
adjust SQL query and typing more; improve user name rendering in fron…
dieknolle3333 May 16, 2024
74d770f
display wk user name
dieknolle3333 May 21, 2024
5d56383
change typing to remove cast
dieknolle3333 May 21, 2024
8a067f7
fix type errors
dieknolle3333 May 21, 2024
46c771c
Merge branch 'master' into show-wk-user-in-vx-workflow-list
dieknolle3333 May 21, 2024
c16deb2
add changelog
dieknolle3333 May 21, 2024
d74759f
improve changelog
dieknolle3333 May 21, 2024
df70035
remove comments
dieknolle3333 May 21, 2024
bbb4984
implement filter
dieknolle3333 May 22, 2024
17c3e80
revert application.conf edits
dieknolle3333 May 22, 2024
60ef98f
fix typing
dieknolle3333 May 22, 2024
8eb8c39
improve key
dieknolle3333 May 22, 2024
eb6f379
Merge branch 'master' into show-wk-user-in-vx-workflow-list
dieknolle3333 May 22, 2024
832eb0d
unify camel case in WorkflowListingRunEntry and RunEntry
dieknolle3333 May 28, 2024
b1e0040
WIP: address review in frontend
dieknolle3333 May 29, 2024
f742567
make wk user optional
dieknolle3333 May 29, 2024
8d7a205
format
dieknolle3333 May 29, 2024
67be5af
revert type reverts
dieknolle3333 May 29, 2024
26e9cda
improve scala camel case
dieknolle3333 May 29, 2024
57d0bcb
remove renaming from SQL code
dieknolle3333 May 29, 2024
9e174b0
revert application.conf edit
dieknolle3333 May 29, 2024
7ad79ce
merge master
dieknolle3333 May 29, 2024
ad5731e
fix sorting of runs
dieknolle3333 May 30, 2024
f734897
Merge branch 'master' into show-wk-user-in-vx-workflow-list
dieknolle3333 May 30, 2024
614de75
revert application.conf edit
dieknolle3333 May 30, 2024
e7fb0f8
Merge branch 'master' into show-wk-user-in-vx-workflow-list
dieknolle3333 Jun 3, 2024
9151c8f
fix camel case of host name
dieknolle3333 Jun 3, 2024
b07d68e
change application.config
dieknolle3333 Jun 3, 2024
67de20c
lint
dieknolle3333 Jun 4, 2024
b7b62be
revert application.conf edits to make pipeline green to create docker…
dieknolle3333 Jun 4, 2024
553cc4f
add mock data
dieknolle3333 Jun 4, 2024
6acc3b7
apply fix to not cache bundle chunk files to backup-show-wk-user-in-v…
MichaelBuessemeyer Jun 5, 2024
5a2e1be
move git commit hash loading dep for webpack build process to dev dep…
MichaelBuessemeyer Jun 5, 2024
3f50bda
undo dev changes
dieknolle3333 Jun 5, 2024
1720d12
adjust formatting
dieknolle3333 Jun 5, 2024
f0fcaaa
Merge branch 'master' into backup-show-wk-user-in-vx-workflow-list
dieknolle3333 Jun 5, 2024
0d0884a
remove redundant initial data fetch
dieknolle3333 Jun 5, 2024
c78a91d
changelog
fm3 Jun 6, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/not-on-master.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
set -Eeuo pipefail

if [ "${CIRCLE_BRANCH}" == "master" ]; then
echo "Skipping this step on master..."
echo "Skipping this step on master..."
else
exec "$@"
fi
1 change: 1 addition & 0 deletions CHANGELOG.unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ For upgrade instructions, please check the [migration guide](MIGRATIONS.released
- Added the option for the owner to lock explorative annotations. Locked annotations cannot be modified by any user. An annotation can be locked in the annotations table and when viewing the annotation via the navbar dropdown menu. [#7801](https://github.com/scalableminds/webknossos/pull/7801)
- Uploading an annotation into a dataset that it was not created for now also works if the dataset is in a different organization. [#7816](https://github.com/scalableminds/webknossos/pull/7816)
- When downloading + reuploading an annotation that is based on a segmentation layer with active mapping, that mapping is now still be selected after the reupload. [#7822](https://github.com/scalableminds/webknossos/pull/7822)
- In the Voxelytics workflow list, the name of the WEBKNOSSOS user who started the job is displayed. [#7794](https://github.com/scalableminds/webknossos/pull/7795)

### Changed
- The "WEBKNOSSOS Changelog" modal now lazily loads its content potentially speeding up the initial loading time of WEBKNOSSOS and thus improving the UX. [#7843](https://github.com/scalableminds/webknossos/pull/7843)
Expand Down
10 changes: 5 additions & 5 deletions app/controllers/VoxelyticsController.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,15 +78,15 @@ class VoxelyticsController @Inject()(
for {
_ <- bool2Fox(runs.nonEmpty) // just asserting once more
workflowTaskCounts <- voxelyticsDAO.findWorkflowTaskCounts(request.identity,
runs.map(_.workflow_hash).toSet,
runs.map(_.workflowHash).toSet,
conf.staleTimeout)
_ <- bool2Fox(workflowTaskCounts.nonEmpty) ?~> "voxelytics.noTaskFound" ~> NOT_FOUND
workflows <- voxelyticsDAO.findWorkflowsByHashAndOrganization(request.identity._organization,
runs.map(_.workflow_hash).toSet)
runs.map(_.workflowHash).toSet)
_ <- bool2Fox(workflows.nonEmpty) ?~> "voxelytics.noWorkflowFound" ~> NOT_FOUND

workflowsAsJson = JsArray(workflows.flatMap(workflow => {
val workflowRuns = runs.filter(run => run.workflow_hash == workflow.hash)
val workflowRuns = runs.filter(run => run.workflowHash == workflow.hash)
if (workflowRuns.nonEmpty) {
val state = workflowRuns.maxBy(_.beginTime).state
val beginTime = workflowRuns.map(_.beginTime).min
Expand Down Expand Up @@ -145,14 +145,14 @@ class VoxelyticsController @Inject()(

// Assemble workflow report JSON
result = Json.obj(
"config" -> voxelyticsService.workflowConfigPublicWrites(mostRecentRun.workflow_config, tasks),
"config" -> voxelyticsService.workflowConfigPublicWrites(mostRecentRun.workflowConfig, tasks),
"artifacts" -> voxelyticsService.artifactsPublicWrites(artifacts),
"runs" -> sortedRuns,
"tasks" -> voxelyticsService.taskRunsPublicWrites(combinedTaskRuns, allTaskRuns),
"workflow" -> Json.obj(
"name" -> workflow.name,
"hash" -> workflowHash,
"yamlContent" -> mostRecentRun.workflow_yamlContent
"yamlContent" -> mostRecentRun.workflowYamlContent
)
)
} yield JsonOk(result)
Expand Down
41 changes: 24 additions & 17 deletions app/models/voxelytics/VoxelyticsDAO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -369,12 +369,12 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
RunEntry(
id = ObjectId(row._1),
name = row._2,
username = row._3,
hostname = row._4,
hostUserName = row._3,
hostName = row._4,
voxelyticsVersion = row._5,
workflow_hash = row._6,
workflow_yamlContent = row._7,
workflow_config = Json.parse(row._8).as[JsObject],
workflowHash = row._6,
workflowYamlContent = row._7,
workflowConfig = Json.parse(row._8).as[JsObject],
state = state,
beginTime = row._10,
endTime = row._11
Expand Down Expand Up @@ -467,7 +467,9 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
COALESCE(tasks.complete, 0) AS tasksComplete,
COALESCE(tasks.cancelled, 0) AS tasksCancelled,
COALESCE(tasks.fileSize, 0) AS fileSize,
COALESCE(tasks.inodeCount, 0) AS inodeCount
COALESCE(tasks.inodeCount, 0) AS inodeCount,
u.firstName,
u.lastName
FROM (${visibleRunsQ(currentUser, allowUnlisted = false)}) r
JOIN (${runsWithStateQ(staleTimeout)}) rs ON rs._id = r._id
LEFT JOIN (
Expand All @@ -490,6 +492,7 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
) ta ON ta._task = t._id
GROUP BY t._run
) tasks ON tasks._run = r._id
LEFT JOIN webknossos.users_ u ON r._user = u._id
WHERE r._organization = $organizationId
""".as[(String,
String,
Expand All @@ -506,7 +509,9 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
Long,
Long,
Long,
Long)])
Long,
Option[String],
Option[String])])
results <- Fox.combined(
r.toList.map(
row =>
Expand All @@ -516,10 +521,10 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
WorkflowListingRunEntry(
id = ObjectId(row._1),
name = row._2,
username = row._3,
hostname = row._4,
hostUserName = row._3,
hostName = row._4,
voxelyticsVersion = row._5,
workflow_hash = row._6,
workflowHash = row._6,
state = state,
beginTime = row._8,
endTime = row._9,
Expand All @@ -531,7 +536,9 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
cancelled = row._14,
fileSize = row._15,
inodeCount = row._16
)
),
userFirstName = row._17,
userLastName = row._18
)))
} yield results
}
Expand Down Expand Up @@ -981,9 +988,9 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
username: String,
hostname: String,
voxelyticsVersion: String,
workflow_hash: String,
workflow_yamlContent: Option[String],
workflow_config: JsValue): Fox[ObjectId] =
workflowHash: String,
workflowYamlContent: Option[String],
workflowConfig: JsValue): Fox[ObjectId] =
for {
_ <- run(q"""
INSERT INTO webknossos.voxelytics_runs (_id, _organization, _user, name, username, hostname, voxelyticsVersion, workflow_hash, workflow_yamlContent, workflow_config)
Expand All @@ -994,9 +1001,9 @@ class VoxelyticsDAO @Inject()(sqlClient: SqlClient)(implicit ec: ExecutionContex
username,
hostname,
voxelyticsVersion,
workflow_hash,
workflow_yamlContent,
workflow_config)}
workflowHash,
workflowYamlContent,
workflowConfig)}
ON CONFLICT (_organization, name)
DO UPDATE SET
_user = EXCLUDED._user,
Expand Down
20 changes: 11 additions & 9 deletions app/models/voxelytics/VoxelyticsService.scala
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@ import scala.util.Try

case class RunEntry(id: ObjectId,
name: String,
username: String,
hostname: String,
hostUserName: String,
hostName: String,
voxelyticsVersion: String,
workflow_hash: String,
workflow_yamlContent: String,
workflow_config: JsObject,
workflowHash: String,
workflowYamlContent: String,
workflowConfig: JsObject,
state: VoxelyticsRunState,
beginTime: Option[Instant],
endTime: Option[Instant])
Expand Down Expand Up @@ -77,14 +77,16 @@ object ChunkCounts {

case class WorkflowListingRunEntry(id: ObjectId,
name: String,
username: String,
hostname: String,
hostUserName: String,
hostName: String,
voxelyticsVersion: String,
workflow_hash: String,
workflowHash: String,
state: VoxelyticsRunState,
beginTime: Option[Instant],
endTime: Option[Instant],
taskCounts: TaskCounts)
taskCounts: TaskCounts,
userFirstName: Option[String],
userLastName: Option[String])

object WorkflowListingRunEntry {
implicit val jsonFormat: OFormat[WorkflowListingRunEntry] = Json.format[WorkflowListingRunEntry]
Expand Down
8 changes: 4 additions & 4 deletions app/views/main.scala.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,21 +33,21 @@
rel="stylesheet"
type="text/css"
media="screen"
href="/assets/bundle/vendors~main.css?nocache=@(webknossos.BuildInfo.commitHash)"
href="/assets/bundle/vendors~main.@(webknossos.BuildInfo.commitHash).css"
/>
<link
rel="stylesheet"
type="text/css"
media="screen"
href="/assets/bundle/main.css?nocache=@(webknossos.BuildInfo.commitHash)"
href="/assets/bundle/main.@(webknossos.BuildInfo.commitHash).css"
/>
<script
data-airbrake-project-id="@(conf.Airbrake.projectID)"
data-airbrake-project-key="@(conf.Airbrake.projectKey)"
data-airbrake-environment-name="@(conf.Airbrake.environment)"
></script>
<script src="/assets/bundle/vendors~main.js?nocache=@(webknossos.BuildInfo.commitHash)"></script>
<script src="/assets/bundle/main.js?nocache=@(webknossos.BuildInfo.commitHash)"></script>
<script src="/assets/bundle/vendors~main.@(webknossos.BuildInfo.commitHash).js"></script>
<script src="/assets/bundle/main.@(webknossos.BuildInfo.commitHash).js"></script>
<script type="text/javascript" src="https://app.olvy.co/script.js" defer="defer"></script>
</head>
<body>
Expand Down
2 changes: 1 addition & 1 deletion frontend/javascripts/admin/admin_rest_api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2330,7 +2330,7 @@ export function getShortLink(key: string): Promise<ShortLink> {
}

// ### Voxelytics
export function getVoxelyticsWorkflows(): Promise<Array<VoxelyticsWorkflowListing>> {
export async function getVoxelyticsWorkflows(): Promise<Array<VoxelyticsWorkflowListing>> {
return Request.receiveJSON("/api/voxelytics/workflows");
}

Expand Down
2 changes: 1 addition & 1 deletion frontend/javascripts/admin/voxelytics/task_list_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ export default function TaskListView({
workflow: { name: readableWorkflowName },
} = report;
const runBeginTimeString = report.runs.reduce(
(r, a) => Math.min(r, a.beginTime.getTime()),
(r, a) => Math.min(r, a.beginTime != null ? a.beginTime.getTime() : Infinity),
Infinity,
);

Expand Down
59 changes: 36 additions & 23 deletions frontend/javascripts/admin/voxelytics/workflow_list_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,30 +25,35 @@ const persistence = new Persistence<Pick<{ searchQuery: string }, "searchQuery">
"workflowList",
);

function parseRunInfo(runInfo: VoxelyticsWorkflowListingRun): VoxelyticsWorkflowListingRun {
function parseRunInfo(runInfo: VoxelyticsWorkflowListingRun) {
return {
...runInfo,
beginTime: new Date(runInfo.beginTime),
beginTime: runInfo.beginTime != null ? new Date(runInfo.beginTime) : null,
endTime: runInfo.endTime != null ? new Date(runInfo.endTime) : null,
} as any as VoxelyticsWorkflowListingRun;
};
}

function parseWorkflowInfo(workflowInfo: VoxelyticsWorkflowListing): VoxelyticsWorkflowListing {
return {
...workflowInfo,
runs: workflowInfo.runs
.map(parseRunInfo)
.sort((a, b) => b.beginTime.getTime() - a.beginTime.getTime()),
runs: workflowInfo.runs.map(parseRunInfo).sort((a, b) => {
if (a.beginTime != null && b.beginTime != null)
return a.beginTime.getTime() - b.beginTime.getTime();
else if (a.beginTime != null) return -1;
else if (b.beginTime != null) return 1;
else return 0;
}),
};
}

function uniqueify<T>(array: Array<T>): Array<T> {
return [...new Set(array)];
}

type RenderRunInfo = VoxelyticsWorkflowListingRun & {
type RenderRunInfo = Omit<VoxelyticsWorkflowListingRun, "userFirstName" | "userLastName"> & {
workflowName: string;
workflowHash: string;
userDisplayName: string | undefined;
children?: Array<VoxelyticsWorkflowListingRun>;
};

Expand Down Expand Up @@ -86,7 +91,13 @@ export default function WorkflowListView() {

usePolling(loadData, VX_POLLING_INTERVAL);

const renderRuns = useMemo(
const getUserDisplayName = (run: VoxelyticsWorkflowListingRun) => {
return run.userFirstName != null || run.userLastName != null
? [run.userFirstName, run.userLastName].join(" ").trim()
: run.hostUserName;
};

const renderRuns: Array<RenderRunInfo> = useMemo(
() =>
workflows.map((workflow) => ({
workflowName: workflow.name,
Expand All @@ -96,18 +107,20 @@ export default function WorkflowListView() {
endTime: workflow.runs[0].endTime,
name: "",
id: "", // used to distinguish between workflows and runs when rendering
username: uniqueify(workflow.runs.map((run) => run.username)).join(", "),
hostname: uniqueify(workflow.runs.map((run) => run.hostname)).join(", "),
hostUserName: uniqueify(workflow.runs.map((run) => run.hostUserName)).join(", "),
hostName: uniqueify(workflow.runs.map((run) => run.hostName)).join(", "),
userDisplayName: uniqueify(workflow.runs.map((run) => getUserDisplayName(run))).join(", "),
voxelyticsVersion: uniqueify(workflow.runs.map((run) => run.voxelyticsVersion)).join(", "),
taskCounts: workflow.taskCounts,
children: workflow.runs.map((run) => ({
workflowName: workflow.name,
workflowHash: workflow.hash,
userDisplayName: getUserDisplayName(run),
...run,
})),
})),
[workflows],
) as any as Array<RenderRunInfo>;
[workflows, getUserDisplayName],
);

function renderProgress(run: RenderRunInfo) {
let label = "";
Expand Down Expand Up @@ -187,26 +200,26 @@ export default function WorkflowListView() {
},
{
title: "User",
dataIndex: "username",
key: "user",
filters: uniqueify(renderRuns.map((run) => run.username)).map((username) => ({
text: username,
value: username,
key: "userName",
dataIndex: "userDisplayName",
filters: uniqueify(renderRuns.map((run) => run.userDisplayName)).map((username) => ({
text: username || "",
value: username || "",
})),
onFilter: (value: string | number | boolean, run: RenderRunInfo) =>
run.username.startsWith(String(value)),
run.userDisplayName?.startsWith(String(value)) || false,
filterSearch: true,
},
{
title: "Hostname",
dataIndex: "hostname",
key: "hostname",
filters: uniqueify(renderRuns.map((run) => run.hostname)).map((hostname) => ({
title: "Host",
dataIndex: "hostName",
key: "host",
filters: uniqueify(renderRuns.map((run) => run.hostName)).map((hostname) => ({
text: hostname,
value: hostname,
})),
onFilter: (value: string | number | boolean, run: RenderRunInfo) =>
run.hostname.startsWith(String(value)),
run.hostName.startsWith(String(value)),
filterSearch: true,
},
{
Expand Down
14 changes: 5 additions & 9 deletions frontend/javascripts/admin/voxelytics/workflow_view.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useParams } from "react-router-dom";
import { useSelector } from "react-redux";
import {
APIOrganization,
VoxelyticsRunInfo,
VoxelyticsRunState,
VoxelyticsTaskConfig,
VoxelyticsTaskConfigWithHierarchy,
Expand Down Expand Up @@ -139,14 +138,11 @@ function parseReport(report: VoxelyticsWorkflowReport): VoxelyticsWorkflowReport
tasks: Object.fromEntries(dag.nodes.map((t) => [t.id, report.config.tasks[t.id]])),
},
dag,
runs: report.runs.map(
(run) =>
({
...run,
beginTime: run.beginTime != null ? new Date(run.beginTime) : null,
endTime: run.endTime != null ? new Date(run.endTime) : null,
}) as VoxelyticsRunInfo,
),
runs: report.runs.map((run) => ({
...run,
beginTime: run.beginTime == null ? null : new Date(run.beginTime),
endTime: run.endTime == null ? null : new Date(run.endTime),
})),
tasks,
};
}
Expand Down
Loading