feat: 并发限流上传

This commit is contained in:
mozzie 2023-08-29 15:43:11 +08:00
parent 063e812448
commit 56f2303fa8
5 changed files with 90 additions and 27 deletions

View File

@ -4,10 +4,16 @@ import { DicomRepository } from "./DicomRepository";
export class DicomService { export class DicomService {
constructor(private dicomRepository: DicomRepository) {} constructor(private dicomRepository: DicomRepository) {}
/**
* 穿pacs
*/
async upload2Pacs(dcmFile: File) { async upload2Pacs(dcmFile: File) {
return await this.dicomRepository.upload2Pacs(dcmFile); return await this.dicomRepository.upload2Pacs(dcmFile);
} }
/**
* dicom徐磊是否在pacs中存在
*/
async existInPacs(p: ExistInPacsDTO) { async existInPacs(p: ExistInPacsDTO) {
return await this.dicomRepository.existInPacs(p); return await this.dicomRepository.existInPacs(p);
} }

View File

@ -2,6 +2,7 @@ import { makeAutoObservable } from "mobx";
import { UserRepository } from "./UserRepository"; import { UserRepository } from "./UserRepository";
import { User } from "./entities/User"; import { User } from "./entities/User";
import { RouteObject } from "react-router"; import { RouteObject } from "react-router";
import { Study } from "@/modules/Admin/Dicom/Upload/DicomUploader/util";
export class UserService { export class UserService {
user: User; user: User;
@ -47,4 +48,11 @@ export class UserService {
async getDmpAnnotators() { async getDmpAnnotators() {
return await this.userRepository.getDmpAnnotators(); return await this.userRepository.getDmpAnnotators();
} }
/**
*
*/
async assignLabelDicom(user: User, study: Study[]) {
console.log(user, study);
}
} }

View File

@ -1,7 +1,7 @@
import { makeAutoObservable } from "mobx"; import { makeAutoObservable } from "mobx";
interface UserProps { interface UserProps {
id?: number | string; id?: number | string | undefined;
username?: string; username?: string;
password?: string; password?: string;
isEnabled?: boolean; isEnabled?: boolean;

View File

@ -5,6 +5,8 @@ import { DicomTable } from "./DicomTable";
import { useDomain } from "@/hook/useDomain"; import { useDomain } from "@/hook/useDomain";
import { Typography } from "antd"; import { Typography } from "antd";
import { useState } from "react"; import { useState } from "react";
import { User } from "@@/domain/User/entities/User";
import { limitConcurrency } from "./limitConcurrency";
const { Text } = Typography; const { Text } = Typography;
@ -29,9 +31,9 @@ export const DicomUpload = (props: DicomUploadProps) => {
const { dcmFileNum, totalFileNum, dcmFileSize } = fileCalculator; const { dcmFileNum, totalFileNum, dcmFileSize } = fileCalculator;
const [selectRows, setSelectedRows] = useState<Study[]>([]); const [selectRows, setSelectedRows] = useState<Study[]>([]);
const [isModalOpen, setIsModalOpen] = useState(false); const [isModalOpen, setIsModalOpen] = useState(false);
const [annotators, setAnnotators] = useState([]); const [annotators, setAnnotators] = useState<User[]>([]);
const [selectAnnotatorId, setSelectAnnotatorId] = useState<string | number>( const [selectAnnotator, setSelectAnnotator] = useState<User | undefined>(
"" undefined
); );
const onUploadFiles = async (study: Study, series: Series) => { const onUploadFiles = async (study: Study, series: Series) => {
@ -45,31 +47,18 @@ export const DicomUpload = (props: DicomUploadProps) => {
if (instances.length === subs.length) { if (instances.length === subs.length) {
openOHIFViewer(StudyInstanceUID, SeriesInstanceUID); openOHIFViewer(StudyInstanceUID, SeriesInstanceUID);
} else { } else {
let fullfilled = 0; const uploadFunc = (f: File) => () => dicomDomainService.upload2Pacs(f);
Promise.all( limitConcurrency(series.subs.map(uploadFunc), 10, (completed, total) => {
series.subs.map((file) => console.log(`${completed} out of ${total} tasks completed.`);
dicomDomainService.upload2Pacs(file).then((res) => {
if (["success", "AlreadyStored"].includes(res.Status)) {
fullfilled++;
}
})
)
).then((res) => {
if (res.length === series.subs.length) {
openOHIFViewer(StudyInstanceUID, SeriesInstanceUID);
}
}); });
} }
}; };
const onClickAssign = () => { const onClickAssign = () => {
userDomainService.getDmpAnnotators().then((res) => { userDomainService.getDmpAnnotators().then((res) => {
console.log(res);
const { data } = res;
setIsModalOpen(true); setIsModalOpen(true);
setAnnotators(data.map((u) => ({ label: u.username, value: u.id }))); setAnnotators(res.data as User[]);
}); });
console.log(selectRows);
}; };
const dcmFileInfo = !!totalFileNum && ( const dcmFileInfo = !!totalFileNum && (
@ -82,10 +71,13 @@ export const DicomUpload = (props: DicomUploadProps) => {
</Space> </Space>
); );
/**
*
*/
const onAssignConfirm = () => { const onAssignConfirm = () => {
if (!selectAnnotatorId) return; if (!selectAnnotator?.id) return;
console.log(selectAnnotatorId); userDomainService.assignLabelDicom(selectAnnotator, selectRows);
setSelectAnnotatorId(0); setSelectAnnotator(undefined);
setIsModalOpen(false); setIsModalOpen(false);
}; };
@ -124,9 +116,15 @@ export const DicomUpload = (props: DicomUploadProps) => {
> >
<Select <Select
style={{ width: "100%", marginBottom: 20 }} style={{ width: "100%", marginBottom: 20 }}
defaultValue={selectAnnotatorId} placeholder="选择标注"
onChange={(e) => setSelectAnnotatorId(e)} value={selectAnnotator?.id as number}
options={annotators} onChange={(id: number) =>
setSelectAnnotator(annotators.find((a) => a.id === id))
}
options={annotators.map((a) => ({
value: a.id,
label: a.username,
}))}
/> />
</Modal> </Modal>
</div> </div>

View File

@ -0,0 +1,51 @@
type PromiseFunction = () => Promise<any>;
/**
*
* @param {Promise<Function>} tasks promise请求函数
* @param {number} maxConcurrency
* @param {} onProgress
* @returns
*/
export async function limitConcurrency(
tasks: PromiseFunction[],
maxConcurrency: number,
onProgress?: (completed: number, total: number) => void
): Promise<any[]> {
const results: any[] = new Array(tasks.length);
let currentIndex = 0;
let completedTasks = 0;
return new Promise((resolve, reject) => {
function executeTask() {
const index = currentIndex;
currentIndex += 1;
if (index >= tasks.length) {
if (results.length === tasks.length) {
resolve(results);
}
return;
}
const task = tasks[index];
task()
.then((result) => {
results[index] = result;
completedTasks++;
if (onProgress) {
onProgress(completedTasks, tasks.length);
}
executeTask();
})
.catch((err) => {
reject(err);
});
}
for (let i = 0; i < Math.min(maxConcurrency, tasks.length); i++) {
executeTask();
}
});
}