@microsoft/windows-admin-center-sdk
Version:
Microsoft - Windows Admin Center Shell
169 lines (167 loc) • 6.88 kB
JavaScript
import { EMPTY, from, of, throwError } from 'rxjs';
import { delay, expand, filter, mergeMap } from 'rxjs/operators';
import { RpcWorkItemClient } from '../rpc/work-item/rpc-work-item-client';
import { RpcWorkItemFindClient } from '../rpc/work-item-find/rpc-work-item-find-client';
import { NotificationState } from './notification-state';
import { WorkItemManager } from './work-item-manager';
import { WorkItemRequestType } from './work-item-request';
/**
* Work item connection to submit a powershell work item, and to query its state.
*/
export class WorkItemConnection {
rpc;
workItemManager;
/**
* Initializes a new instance of the WorkItemConnection class.
*
* @param rpc the RPC.
* @param gatewayConnection the gateway connection.
* @param notificationConnection the notification connection.
*/
constructor(rpc, gatewayConnection, nodeConnection, notificationConnection) {
this.rpc = rpc;
if (notificationConnection.notificationManager) {
this.workItemManager = new WorkItemManager(this.rpc, gatewayConnection, nodeConnection, notificationConnection);
}
}
/**
* Submit a work item either directly to NotificationManager or through RPC.
*
* @param nodeName the name of the node to submit the item against.
* @param request the work item request.
* @return Observable the observable of WorkItemResult object.
*/
submit(nodeName, request) {
const data = {
...request,
...{
type: WorkItemRequestType.WorkItemSubmit,
sourceName: MsftSme.self().Environment.name,
nodeName: nodeName,
timestamp: Date.now()
}
};
if (this.workItemManager) {
return this.workItemManager.submitWorkItem(data);
}
// configure PowerShell module name before sending to RPC.
if (data.powerShellCommand && data.powerShellCommand.module == null && MsftSme.self().Init.powerShellModuleName) {
data.powerShellCommand.module = MsftSme.self().Init.powerShellModuleName;
}
const interval = 100;
return from(RpcWorkItemClient.submitOrQueryWorkItem(this.rpc, data))
.pipe(expand((result) => {
if (result.id) {
return EMPTY;
}
return of(result)
.pipe(delay(interval), mergeMap(() => {
const pollingData = {
type: WorkItemRequestType.StateQuery,
sourceName: MsftSme.self().Environment.name,
timestamp: Date.now(),
sequenceId: result.sequenceId
};
return RpcWorkItemClient.submitOrQueryWorkItem(this.rpc, pollingData);
}));
}), filter((result) => !!result.id));
}
/**
* Query a work item either directly to NotificationManager or through RPC.
*
* @param id the ID of the work item.
* @return Observable the observable of WorkItemResult object.
*/
query(id) {
const data = {
type: WorkItemRequestType.StateQuery,
sourceName: MsftSme.self().Environment.name,
timestamp: Date.now(),
id: id
};
if (this.workItemManager) {
return this.workItemManager.queryWorkItem(data);
}
return from(RpcWorkItemClient.submitOrQueryWorkItem(this.rpc, data));
}
/**
* Find existing work item with state.
*
* @param nodeName the node name.
* @param moduleName the module name.
* @param typeId the type ID.
* @return Observable<WorkItemFindResult> the observable of WorkItemFindResult.
*/
find(nodeName, moduleName, typeId) {
const data = {
sourceName: MsftSme.self().Environment.name,
nodeName: nodeName,
moduleName: moduleName,
typeId: typeId
};
if (this.workItemManager) {
return of(this.workItemManager.notificationConnection.notificationManager.workItemFind(data));
}
return from(RpcWorkItemFindClient.workItemFind(this.rpc, data));
}
/**
* Submit a work item either directly to NotificationManager or through RPC, and wait for completion.
*
* @param nodeName the name of the node to submit the work item against
* @param request the work item request.
* @param timeout the timeout milliseconds. (optional, default forever until unsubscribe)
* @param interval the interval period milliseconds. (optional, default 1 sec)
* @return Observable the observable of WorkItemResult object.
*/
submitAndWait(nodeName, request, timeout = 0, interval = 1000) {
return this.waitObservable(this.submit(nodeName, request), timeout, interval);
}
/**
* Wait for existing work item with state.
*
* @param workItemResult the work item result to wait for the final result.
* @param timeout the timeout milliseconds. (optional, default forever until unsubscribe)
* @param interval the interval period milliseconds. (optional, default 1 sec)
* @return Observable<WorkItemFindResult> the observable of WorkItemFindResult.
*/
wait(workItemResult, timeout = 0, interval = 1000) {
if (!workItemResult) {
return of(null);
}
return this.waitObservable(of(workItemResult), timeout, interval);
}
/**
* Check if work item result was finished.
*
* @param result the work item result.
* @return boolean true if work item was completed with success or error.
*/
isFinished(result) {
if (result.state !== NotificationState.Started && result.state !== NotificationState.InProgress) {
return true;
}
return false;
}
/**
* Wait for existing work item with state.
*
* @param workItemResult the work item result to wait for the final result.
* @param timeout the timeout milliseconds. (optional, default forever until unsubscribe)
* @param interval the interval period milliseconds. (optional, default 1 sec)
* @return Observable<WorkItemFindResult> the observable of WorkItemFindResult.
*/
waitObservable(observable, timeout = 0, interval = 1000) {
return observable
.pipe(expand((result, index) => {
if (this.isFinished(result)) {
return EMPTY;
}
else if (timeout > 0 && interval * index > timeout) {
return throwError(() => new Error('timeout'));
}
return of(result)
.pipe(delay(interval), mergeMap(() => this.query(result.id)));
}), filter((result) => this.isFinished(result)));
}
}
//# sourceMappingURL=work-item-connection.js.map