forked from rucio/webui
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
sdk: add BaseMultiCallStreamUseCase rucio#226
- Loading branch information
Showing
12 changed files
with
346 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
name: SDK Tests | ||
on: | ||
push: | ||
branches: | ||
- master | ||
pull_request: | ||
branches: | ||
- master | ||
jobs: | ||
test: | ||
name: Test WebUI SDK | ||
strategy: | ||
matrix: | ||
node-version: [16.14.0, 18.5.0] | ||
runs-on: ubuntu-latest | ||
steps: | ||
- uses: actions/checkout@v3 | ||
- name: Use Node.js 18.x | ||
uses: actions/setup-node@v3 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
- name: Install dependencies | ||
run: npm install | ||
- name: Run SDK Tests | ||
run: npm run test:sdk | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
29 changes: 29 additions & 0 deletions
29
src/lib/core/use-case/list-dids-usecase-pipeline-element.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import { BaseMultiCallUseCasePipelineElement } from "@/lib/sdk/usecase-stream-element"; | ||
import { inject } from "inversify"; | ||
import { ListDIDDTO } from "../dto/did-dto"; | ||
import { ListDIDsError, ListDIDsRequest, ListDIDsResponse } from "../usecase-models/list-dids-usecase-models"; | ||
|
||
class ListDIDsGetListOfDIDs extends BaseMultiCallUseCasePipelineElement< | ||
ListDIDsRequest, | ||
ListDIDsResponse, | ||
ListDIDsError, | ||
ListDIDDTO | ||
>{ | ||
constructor( | ||
@inject('didGateway') private didGateway: DIDGatewayOutputPort, | ||
) { | ||
super(requestModel, responseModel) | ||
} | ||
makeGatewayRequest(requestModel: ListDIDsRequest): Promise<ListDIDDTO> { | ||
throw new Error("Method not implemented."); | ||
} | ||
processDTO(dto: ListDIDDTO): { data: ListDIDsResponse | ListDIDsError; status: "success" | "error"; } { | ||
throw new Error("Method not implemented."); | ||
} | ||
handleGatewayError(error: ListDIDDTO): ListDIDsError { | ||
throw new Error("Method not implemented."); | ||
} | ||
transformResponseModel(responseModel: ListDIDsResponse, dto: ListDIDDTO): ListDIDsResponse { | ||
throw new Error("Method not implemented."); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
import { injectable } from "inversify"; | ||
import type { ListDIDsInputPort, ListDIDsOutputPort } from "@/lib/core/port/primary/list-dids-ports"; | ||
import type DIDGatewayOutputPort from "@/lib/core/port/secondary/did-gateway-output-port"; | ||
import { ListDIDDTO } from "../dto/did-dto"; | ||
import { ListDIDsError, ListDIDsRequest, ListDIDsResponse } from "../usecase-models/list-dids-usecase-models"; | ||
import { parseDIDString } from "@/lib/common/did-utils"; | ||
import { DID } from "../entity/rucio"; | ||
import { BaseMultiCallStreamableUseCase, BaseStreamingUseCase } from "@/lib/sdk/usecase"; | ||
import { AuthenticatedRequestModel } from "@/lib/sdk/usecase-models"; | ||
|
||
@injectable() | ||
class ListDIDsUseCase2 extends BaseMultiCallStreamableUseCase<ListDIDsRequest, ListDIDsResponse, ListDIDsError, DID> implements ListDIDsInputPort { | ||
validateFinalResponseModel(responseModel: ListDIDsResponse): { isValid: boolean; errorModel?: ListDIDsError | undefined; } { | ||
throw new Error("Method not implemented."); | ||
} | ||
constructor( | ||
protected presenter: ListDIDsOutputPort, | ||
private didGateway: DIDGatewayOutputPort, | ||
) { | ||
super(presenter) | ||
this.didGateway = didGateway; | ||
} | ||
|
||
validateRequestModel(requestModel: AuthenticatedRequestModel<ListDIDsRequest>): ListDIDsError | undefined { | ||
let scope: string; | ||
let name: string; | ||
try{ | ||
let didComponents = parseDIDString(requestModel.query); | ||
scope = didComponents.scope; | ||
name = didComponents.name; | ||
} catch (error: any) { | ||
return { | ||
status: 'error', | ||
error: 'Invalid DID Query', | ||
message: (error as Error).message, | ||
} as ListDIDsError | ||
} | ||
} | ||
|
||
// async makeGatewayRequest(requestModel: AuthenticatedRequestModel<ListDIDsRequest>): Promise<ListDIDDTO> { | ||
// const { scope, name } = parseDIDString(requestModel.query); | ||
// const listDIDDTO: ListDIDDTO = await this.didGateway.listDIDs(requestModel.rucioAuthToken, scope, name, requestModel.type); | ||
// return listDIDDTO; | ||
// } | ||
|
||
// handleGatewayError(error: ListDIDDTO): ListDIDsError { | ||
// let errorType = 'Unknown Error' | ||
// if(error.error === 'Invalid Auth Token') { | ||
// errorType = 'Invalid Request' | ||
// } | ||
// else if(error.error !== 'Unknown Error') { | ||
// errorType = 'Invalid DID Query' | ||
// } | ||
|
||
// return { | ||
// error: errorType, | ||
// message: `${error.error}: ${error.message}`, | ||
// } as ListDIDsError | ||
// } | ||
|
||
// processStreamedData(dto: DID): { data: ListDIDsResponse | ListDIDsError; status: "success" | "error"; } { | ||
// const responseModel: ListDIDsResponse = { | ||
// status: 'success', | ||
// name: dto.name, | ||
// scope: dto.scope, | ||
// did_type: dto.did_type, | ||
// length: 0, | ||
// bytes: 0, | ||
// } | ||
// return { | ||
// data: responseModel, | ||
// status: 'success', | ||
// } | ||
// } | ||
} | ||
|
||
export default ListDIDsUseCase2; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
import { Transform } from 'stream'; | ||
import { BaseDTO } from './dto'; | ||
import { BaseErrorResponseModel, BaseResponseModel } from './usecase-models'; | ||
|
||
export abstract class BaseMultiCallUseCasePipelineElement<TRequestModel, TResponseModel extends BaseResponseModel, TErrorModel extends BaseErrorResponseModel, TDTO extends BaseDTO> extends Transform { | ||
protected requestModel: TRequestModel | ||
protected responseModel: TResponseModel | ||
|
||
constructor(requestModel: TRequestModel, responseModel: TResponseModel) { | ||
super({ objectMode: true }); | ||
this.requestModel = requestModel | ||
this.responseModel = responseModel | ||
} | ||
|
||
/** | ||
* Makes a gateway request with the given request model. | ||
* @param requestModel The request model to send to the gateway. | ||
* @returns A promise that resolves with the DTO returned by the gateway. | ||
*/ | ||
abstract makeGatewayRequest(requestModel: TRequestModel): Promise<TDTO> | ||
|
||
/** | ||
* Handles the DTO returned by the gateway. | ||
* This method is called when the gateway returns a DTO with a status of `success`. | ||
* @param dto The DTO returned by the gateway. | ||
* @returns An object that contains the response or error model and the status of processing the DTO. | ||
*/ | ||
abstract processDTO(dto: TDTO): { | ||
data: TResponseModel | TErrorModel | ||
status: 'success' | 'error' | ||
} | ||
|
||
/** | ||
* Handles a gateway error by converting it to an error model. | ||
* This method is called when the gateway returns a DTO with a status of `error`. | ||
* @param error The DTO returned by the gateway. | ||
* @returns An error model that represents the gateway error. | ||
*/ | ||
abstract handleGatewayError(error: TDTO): TErrorModel | ||
|
||
/** | ||
* Modifies the response model of the use case with the data returned by the gateway. | ||
* @param responseModel The response model to transform. | ||
* @param dto The valid DTO returned by the gateway. | ||
*/ | ||
abstract transformResponseModel(responseModel: TResponseModel, dto: TDTO): TResponseModel | ||
|
||
/** | ||
* Processes the response and DTO returned by the gateway. | ||
* @param response The DTO returned by the gateway. | ||
* @returns The ResponseModel or ErrorModel returned, based on processing of the DTO. | ||
*/ | ||
processGatewayResponse(response: TDTO): TResponseModel | TErrorModel { | ||
if (response.status === 'success') { | ||
const { status, data } = this.processDTO(response) | ||
if( status === 'success') { | ||
return data as TResponseModel | ||
} | ||
return data as TErrorModel | ||
} | ||
const errorModel: TErrorModel = this.handleGatewayError(response) | ||
return errorModel | ||
} | ||
|
||
async exceute(): Promise<TResponseModel | TErrorModel> { | ||
const dto = await this.makeGatewayRequest(this.requestModel) | ||
const data: TResponseModel | TErrorModel = this.processGatewayResponse(dto) | ||
if(data.status === 'error') { | ||
return Promise.reject(data) | ||
} | ||
const transformedResponseModel = this.transformResponseModel(this.responseModel, dto) | ||
return Promise.resolve(transformedResponseModel) | ||
} | ||
|
||
_transform(chunk: TResponseModel, encoding: BufferEncoding, callback: (error?: Error, data?: TResponseModel | TErrorModel) => void): void { | ||
this.responseModel = chunk | ||
this.exceute().then((data) => { | ||
this.push(data) | ||
callback(undefined, data) // TODO check if data is not pushed twice | ||
}).catch((error) => { | ||
this.emit('error', error) | ||
callback(error) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.