UNPKG

@microsoft/windows-admin-center-sdk

Version:

Microsoft - Windows Admin Center Shell

169 lines (167 loc) 6.88 kB
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