Refresh Session Metadata
For users of Editor 2024 C1 and older, there are occasions when a session is in progress but its owner can’t see it within the My Work tab in Session Manager. An administrator can see the session in Solution Center. This is caused by session metadata being out of sync. We created a workflow called Refresh Session Metadata to resolve this situation.
This workflow uses the ancestral ID of the out-of-the-box (OOTB) Session Manager workflow, enabling the refresh of metadata for the impacted session. It is a hybrid hosted/client workflow that updates the StatusToUsers collection.
To execute this workflow, in the Solution Center Workflows plugin, on the Run History tab, select the impacted Session Manager workflow. In the center pane, from the Tools drop-down, select Refresh Session Metadata. A message appears saying that this workflow triggered the event to refresh the session metadata. Click OK. From the Run History list, click the Refresh button and note that a new entry appears in the list called Refresh Session Information. Back in Session Manager, the user can refresh their Session Manager list. The impacted session then appears in the My Work tab of Session Manager.
Refresh Session Metadata
digraph workflow {
entry[
se_type0 = RunHistoryToolTrigger,
se_displayName0 = "Refresh Session Metadata"
se_sortOrder0 = 0,
se_visibilityCondition0 = "(ctx, log) => {
return ctx.Event.workflowAncestralId == \"d88e3325-705a-4814-b483-2b08b836c3bc\";
}",
se_type1 = Action
se_action1 = "(ctx, log) => {
ctx.State.SessionId = ctx.Event.runningWorkflow.instance?.customStatus.Event.associatedSessionId;
}"
se_type2 = CopyToClipboard,
se_determineData2 = "(ctx, log) => {
return JsonConvert.SerializeObject(\"entry\");
}"
];
getSession[
se_type0 = Api,
se_method0 = GET
se_modifyRequest0 = "(request, ctx, log) => {
request.RequestUri = new Uri($\"api/v1/sessions/{ctx.State.SessionId}\", UriKind.Relative);
}",
se_resultVariable0 = "Session"
se_service0 = SessionManager,
se_type2 = CopyToClipboard,
se_determineData2 = "(ctx, log) => {
return JsonConvert.SerializeObject(\"getSession\");
}"
];
getAssignments[
se_type0 = Api,
se_method0 = GET,
se_service0 = Editor,
se_modifyRequest0 = "(request, ctx, log) => {
var q = $\"select * from c where c.associatedSessionId = '{ctx.State.SessionId}' and (c.status = 0 or c.status = 1 or c.status = 2)\";
request.RequestUri = new Uri($\"api/v1/assignments?q={q}\", UriKind.Relative);
}",
se_resultVariable0 = AssignmentResources
se_type2 = CopyToClipboard,
se_determineData2 = "(ctx, log) => {
return JsonConvert.SerializeObject(ctx.State);
}"
];
checkSessionMetadata[
se_type0 = Action,
se_action0 = "(ctx, log) => {
var statusToUsers = ctx.State.Session.statusToUsers;
var assignment = ctx.State.AssignmentResources.values[0];
if(assignment.assignedTo == null && statusToUsers?.Unassigned == null){
ctx.State.SessionManagerMessage = new {
workflowSessionId = Guid.NewGuid().ToString(),
sessionId = ctx.State.SessionId,
assignmentStatus = 0,
};
}
else if(assignment.assignedTo != null && statusToUsers?.Assigned == null)
{
ctx.State.SessionManagerMessage = new {
workflowSessionId = Guid.NewGuid().ToString(),
sessionId = ctx.State.SessionId,
userId = assignment.assignedTo,
assignmentStatus = 1 //always set assigned to support the older queries
};
}
else if(statusToUsers?.Assigned?.Count > 1)
{
//Multiple assigned users in metadata, just fire the message
ctx.State.SessionManagerMessage = new {
workflowSessionId = Guid.NewGuid().ToString(),
sessionId = ctx.State.SessionId,
userId = assignment.assignedTo,
assignmentStatus = 1 //always set assigned to support the older queries
};
}
else
{
//Check if the user that is in the inprogress or assigned collection matches the user on the assignment
var assignedUser = assignment.assignedTo.ToString();
var assignedUserStr = statusToUsers?.Assigned != null ? statusToUsers?.Assigned[0].ToString() : string.Empty;
ctx.State.AssignedUser = assignedUser;
if(!string.IsNullOrEmpty(assignedUserStr) && !assignedUser.Equals(assignedUserStr))
{
ctx.State.SessionManagerMessage = new {
workflowSessionId = Guid.NewGuid().ToString(),
sessionId = ctx.State.SessionId,
userId = assignment.assignedTo,
assignmentStatus = 1 //always set assigned to support the older queries
};
}
else{
ctx.State.SessionManagerMessage = null;
}
}
}",
se_type2 = CopyToClipboard,
se_determineData2 = "(ctx, log) => {
return JsonConvert.SerializeObject(ctx.State);
}"
];
presentNoOpenAssignmentError[
se_type0 = PromptUser,
se_cardTemplate0 = "{
\"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
\"type\": \"AdaptiveCard\",
\"version\": \"1.3\",
\"body\": [
{
\"type\": \"TextBlock\",
\"text\": \"No Open Assignments Detected. Unable to Refresh.\"
},
{
\"type\": \"ActionSet\",
\"actions\": [
{
\"type\": \"Action.Submit\",
\"title\": \"Ok\"
}
]
}
]}"
];
presentMultipleOpenAssignmentError[
se_type0 = PromptUser,
se_cardTemplate0 = "{
\"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
\"type\": \"AdaptiveCard\",
\"version\": \"1.3\",
\"body\": [
{
\"type\": \"TextBlock\",
\"text\": \"Multiple Open Assignments Detected. Unable to Refresh.\"
},
{
\"type\": \"ActionSet\",
\"actions\": [
{
\"type\": \"Action.Submit\",
\"title\": \"Ok\"
}
]
}
]}"
];
presentNoWorkMessage[
se_type0 = PromptUser,
se_cardTemplate0 = "{
\"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
\"type\": \"AdaptiveCard\",
\"version\": \"1.3\",
\"body\": [
{
\"type\": \"TextBlock\",
\"text\": \"Session metadata matches expectations, exiting.\"
},
{
\"type\": \"ActionSet\",
\"actions\": [
{
\"type\": \"Action.Submit\",
\"title\": \"Ok\"
}
]
}
]}"
];
presentWorkflowTriggeredMessage[
se_type0 = PromptUser,
se_cardTemplate0 = "{
\"$schema\": \"http://adaptivecards.io/schemas/adaptive-card.json\",
\"type\": \"AdaptiveCard\",
\"version\": \"1.3\",
\"body\": [
{
\"type\": \"TextBlock\",
\"text\": \"Triggered the event to refresh session metadata, please refresh run history for more details.\"
},
{
\"type\": \"ActionSet\",
\"actions\": [
{
\"type\": \"Action.Submit\",
\"title\": \"Ok\"
}
]
}
]}"
];
callOnDemandWorkflow[
se_type0 = Api,
se_method0 = POST
se_modifyRequest0 = "(request, ctx, log) => {
var body = new {
WorkflowMetadataId = \"950e6965-453c-4603-89d4-2cc628f44309\",
workflowAncestralId = \"68361d55-4bb4-481f-84c0-b3843cb1374a\",
workflowSessionId = Guid.NewGuid().ToString(),
state = ctx.State.SessionManagerMessage
};
request.RequestUri = new Uri($\"api/v1/runningworkflow/dynamic\", UriKind.Relative);
request.Content = new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, \"application/json\");
}",
se_resultVariable0 = CallResult
se_service0 = ExternalEvents
se_type2 = CopyToClipboard,
se_determineData2 = "(ctx, log) => {
return JsonConvert.SerializeObject(ctx.State);
}",
];
entry->getSession->getAssignments;
getAssignments->presentMultipleOpenAssignmentError[
se_type = Condition,
se_condition="(ctx, log) => {
return ctx.State.AssignmentResources.values.Count > 1;
}"
]
getAssignments->presentNoOpenAssignmentError[
se_type = Condition,
se_condition="(ctx, log) => {
return ctx.State.AssignmentResources.values.Count == 0;
}"
]
getAssignments->checkSessionMetadata[
se_type = Condition,
se_condition="(ctx, log) => {
return ctx.State.AssignmentResources.values.Count == 1;
}"
];
checkSessionMetadata->callOnDemandWorkflow[
se_type = Condition,
se_condition="(ctx, log) => {
return ctx.State.SessionManagerMessage != null;
}"
];
checkSessionMetadata->presentNoWorkMessage[
se_type = Condition,
se_condition="(ctx, log) => {
return ctx.State.SessionManagerMessage == null;
}"
];
presentNoWorkMessage->exit;
presentMultipleOpenAssignmentError->exit;
presentNoOpenAssignmentError->exit;
callOnDemandWorkflow->presentWorkflowTriggeredMessage->exit;
}