UNPKG

@hpcc-js/comms

Version:
237 lines (217 loc) 10.7 kB
import { Cache, exists, StateObject } from "@hpcc-js/util"; import { IConnection, IOptions } from "../connection.ts"; import { WsDfu } from "../services/wsDFU.ts"; import { isECLResult, WorkunitsService, WsWorkunits } from "../services/wsWorkunits.ts"; import { parseXSD, XSDSchema, XSDXMLNode } from "./xsdParser.ts"; export class GlobalResultCache extends Cache<{ BaseUrl: string, Wuid: string, ResultName: string }, Result> { constructor() { super((obj) => { return `${obj.BaseUrl}-${obj.Wuid}-${obj.ResultName}`; }); } } const _results = new GlobalResultCache(); export type ResultFilter = { [key: string]: string | number }; export interface ECLResultEx extends WsWorkunits.ECLResult { Wuid: string; ResultName?: string; ResultSequence?: number; LogicalFileName?: string; NodeGroup?: string; ResultViews: string[]; } export interface WUResultResponseEx { Exceptions: WsWorkunits.Exceptions; Wuid: string; Sequence: WsWorkunits.int; LogicalName: string; Cluster: string; Name: string; Start: WsWorkunits.long; Requested: WsWorkunits.int; Count: WsWorkunits.int; Total: WsWorkunits.long; Result: { [key: string]: any[] } & { XmlSchema?: { xml: string; }; }; } export type UResulState = ECLResultEx & WsDfu.DFULogicalFile; export type IResulState = ECLResultEx | WsDfu.DFULogicalFile; export class Result extends StateObject<UResulState, IResulState> implements ECLResultEx { protected connection: WorkunitsService; get BaseUrl() { return this.connection.baseUrl; } protected xsdSchema: XSDSchema; get properties(): WsWorkunits.ECLResult { return this.get(); } get Wuid(): string { return this.get("Wuid"); } get ResultName(): string | undefined { return this.get("ResultName"); } get ResultSequence(): number | undefined { return this.get("ResultSequence"); } get LogicalFileName(): string | undefined { return this.get("LogicalFileName"); } get Name(): string { return this.get("Name"); } get Sequence(): number { return this.get("Sequence"); } get Value(): string { return this.get("Value"); } get Link(): string { return this.get("Link"); } get FileName(): string { return this.get("FileName"); } get IsSupplied(): boolean { return this.get("IsSupplied"); } get ShowFileContent() { return this.get("ShowFileContent"); } get Total(): number { return this.get("Total"); } get ECLSchemas(): WsWorkunits.ECLSchemas { return this.get("ECLSchemas"); } get NodeGroup(): string { return this.get("NodeGroup"); } get ResultViews(): string[] { return this.get("ResultViews"); } get XmlSchema(): string { return this.get("XmlSchema"); } static attach(optsConnection: IOptions | IConnection | WorkunitsService, wuid: string, name: string); static attach(optsConnection: IOptions | IConnection | WorkunitsService, wuid: string, sequence: number); static attach(optsConnection: IOptions | IConnection | WorkunitsService, wuid: string, eclResult: WsWorkunits.ECLResult, resultViews: string[]); static attach(optsConnection: IOptions | IConnection | WorkunitsService, wuid: string, name_sequence_eclResult?: string | number | WsWorkunits.ECLResult, resultViews?: string[]): Result { let retVal: Result; if (Array.isArray(resultViews)) { retVal = _results.get({ BaseUrl: optsConnection.baseUrl, Wuid: wuid, ResultName: (name_sequence_eclResult as WsWorkunits.ECLResult).Name }, () => { return new Result(optsConnection, wuid, name_sequence_eclResult as WsWorkunits.ECLResult, resultViews); }); retVal.set(name_sequence_eclResult as any); } else if (typeof resultViews === "undefined") { if (typeof name_sequence_eclResult === "number") { retVal = _results.get({ BaseUrl: optsConnection.baseUrl, Wuid: wuid, ResultName: "Sequence_" + name_sequence_eclResult }, () => { return new Result(optsConnection, wuid, name_sequence_eclResult); }); } else if (typeof name_sequence_eclResult === "string") { retVal = _results.get({ BaseUrl: optsConnection.baseUrl, Wuid: wuid, ResultName: name_sequence_eclResult }, () => { return new Result(optsConnection, wuid, name_sequence_eclResult); }); } } return retVal; } static attachLogicalFile(optsConnection: IOptions | IConnection | WorkunitsService, nodeGroup: string, logicalFile: string) { return _results.get({ BaseUrl: optsConnection.baseUrl, Wuid: nodeGroup, ResultName: logicalFile }, () => { return new Result(optsConnection, nodeGroup, logicalFile, true); }); } private constructor(optsConnection: IOptions | IConnection | WorkunitsService, wuid: string, name: string); private constructor(optsConnection: IOptions | IConnection | WorkunitsService, wuid: string, sequence: number); private constructor(optsConnection: IOptions | IConnection | WorkunitsService, wuid: string, eclResult: WsWorkunits.ECLResult, resultViews: string[]); private constructor(optsConnection: IOptions | IConnection | WorkunitsService, nodeGroup: string, logicalFile: string, isLogicalFiles: boolean); private constructor(optsConnection: IOptions | IConnection | WorkunitsService, wuid_NodeGroup: string, name_sequence_eclResult_logicalFile?: string | number | WsWorkunits.ECLResult, resultViews_isLogicalFile?: any[] | boolean) { super(); if (optsConnection instanceof WorkunitsService) { this.connection = optsConnection; } else { this.connection = new WorkunitsService(optsConnection); } if (typeof resultViews_isLogicalFile === "boolean" && resultViews_isLogicalFile === true) { this.set({ NodeGroup: wuid_NodeGroup, LogicalFileName: name_sequence_eclResult_logicalFile } as ECLResultEx); } else if (isECLResult(name_sequence_eclResult_logicalFile) && Array.isArray(resultViews_isLogicalFile)) { this.set({ ...name_sequence_eclResult_logicalFile, Wuid: wuid_NodeGroup, ResultName: name_sequence_eclResult_logicalFile.Name, ResultViews: resultViews_isLogicalFile } as ECLResultEx); } else if (typeof resultViews_isLogicalFile === "undefined") { if (typeof name_sequence_eclResult_logicalFile === "number") { this.set({ Wuid: wuid_NodeGroup, ResultSequence: name_sequence_eclResult_logicalFile } as ECLResultEx); } else if (typeof name_sequence_eclResult_logicalFile === "string") { this.set({ Wuid: wuid_NodeGroup, ResultName: name_sequence_eclResult_logicalFile } as ECLResultEx); } else { console.warn("Unknown Result.attach (1)"); } } else { console.warn("Unknown Result.attach (2)"); } } isComplete() { return this.Total !== -1; } private _fetchXMLSchemaPromise: Promise<XSDSchema | null>; fetchXMLSchema(refresh = false): Promise<XSDSchema | null> { if (!this._fetchXMLSchemaPromise || refresh) { this._fetchXMLSchemaPromise = this.WUResult().then(response => { if (response.Result?.XmlSchema?.xml) { this.xsdSchema = parseXSD(response.Result.XmlSchema.xml); return this.xsdSchema; } return null; }); } return this._fetchXMLSchemaPromise; } async refresh(): Promise<this> { await this.fetchRows(0, 1, true); return this; } fetchRows(from: number = 0, count: number = -1, includeSchema: boolean = false, filter: ResultFilter = {}, abortSignal?: AbortSignal): Promise<any[]> { return this.WUResult(from, count, !includeSchema, filter, abortSignal).then((response) => { const result: any = response.Result; delete response.Result; // Do not want it in "set" this.set({ ...response } as any); if (exists("XmlSchema.xml", result)) { this.xsdSchema = parseXSD(result.XmlSchema.xml); } if (exists("Row", result)) { return result.Row; } else if (this.ResultName && exists(this.ResultName, result)) { return result[this.ResultName].Row; } return []; }); } rootField(): XSDXMLNode | null { if (!this.xsdSchema) return null; return this.xsdSchema.root; } fields(): XSDXMLNode[] { if (!this.xsdSchema) return []; return this.xsdSchema.root.children(); } protected WUResult(start: number = 0, count: number = 1, suppressXmlSchema: boolean = false, filter: { [key: string]: string | number } = {}, abortSignal?: AbortSignal): Promise<WUResultResponseEx> { const FilterBy = { NamedValue: { itemcount: 0 } }; for (const key in filter) { FilterBy.NamedValue[FilterBy.NamedValue.itemcount++] = { Name: key, Value: filter[key] }; } const request: Partial<WsWorkunits.WUResult> = { FilterBy } as any; if (this.Wuid && this.ResultName !== undefined) { request.Wuid = this.Wuid; request.ResultName = this.ResultName; } else if (this.Wuid && this.ResultSequence !== undefined) { request.Wuid = this.Wuid; request.Sequence = this.ResultSequence; } else if (this.LogicalFileName && this.NodeGroup) { request.LogicalName = this.LogicalFileName; request.Cluster = this.NodeGroup; } else if (this.LogicalFileName) { request.LogicalName = this.LogicalFileName; } request.Start = start; request.Count = count; request.SuppressXmlSchema = suppressXmlSchema; return this.connection.WUResult(request, abortSignal).then((response: unknown) => { return response as WUResultResponseEx; }); } } export class ResultCache extends Cache<WsWorkunits.ECLResult, Result> { constructor() { super((obj) => { return Cache.hash([obj.Sequence, obj.Name, obj.Value, obj.FileName]); }); } }