Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c7f1a63
EW-1317: Test other upload structure.
mkreuzkam-cap Nov 6, 2025
3ac4f42
Use allSettled.
mkreuzkam-cap Nov 6, 2025
d7932f8
Add logging.
mkreuzkam-cap Nov 6, 2025
67d9db3
Merge branch 'main' into EW-1317
mkreuzkam-cap Nov 6, 2025
bef559a
Try for loop.
mkreuzkam-cap Nov 6, 2025
03af6e0
Try keepAlive for axios.
mkreuzkam-cap Nov 7, 2025
90a0dc7
Revert "Try keepAlive for axios."
SimoneRadtke-Cap Nov 11, 2025
577b018
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Nov 11, 2025
7f4af8e
EW-1317 Try solution with plimit
SimoneRadtke-Cap Nov 14, 2025
6f5cda7
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Nov 14, 2025
e2f1293
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Nov 26, 2025
c544c60
EW-1317 Next try with pLimit
SimoneRadtke-Cap Nov 26, 2025
94203cf
EW-1317 pLimit lowered and axios timeout added
SimoneRadtke-Cap Nov 27, 2025
8f98b74
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 9, 2025
4370c8e
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 9, 2025
05e82f7
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 9, 2025
6e6f455
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 11, 2025
6d60d09
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 12, 2025
fd8bb5b
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 15, 2025
144e9bb
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 15, 2025
c9ebb51
Revert "EW-1317 Try solution with plimit"
SimoneRadtke-Cap Dec 16, 2025
b03943b
Revert "EW-1317 Next try with pLimit"
SimoneRadtke-Cap Dec 16, 2025
623ddfe
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 16, 2025
5699e3a
EW-1317 Add retry wrapper
SimoneRadtke-Cap Dec 17, 2025
8f59d0d
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 17, 2025
918f317
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 18, 2025
beac2b0
EW-1317 Add retry to createCardElement
SimoneRadtke-Cap Dec 19, 2025
f484908
Merge branch 'main' into EW-1317
SimoneRadtke-Cap Dec 19, 2025
e3918ad
EW-1317 Add retry to createCard and createCardElementWithResource
SimoneRadtke-Cap Dec 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions apps/server/src/infra/boards-client/boards-client.module.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import { Module, Scope } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { REQUEST } from '@nestjs/core';
import { Request } from 'express';
import { JwtExtractor } from '@shared/common/utils';
import axios from 'axios';
import { Request } from 'express';
import { BoardsClientAdapter } from './boards-client.adapter';
import { BoardsClientConfig } from './boards-client.config';
import { Configuration, BoardApi } from './generated';
import { BoardApi, Configuration } from './generated';

@Module({
providers: [
Expand All @@ -21,7 +22,8 @@ import { Configuration, BoardApi } from './generated';
accessToken,
});

return new BoardApi(configuration);
const axiosInstance = axios.create({ timeout: 60000 });
return new BoardApi(configuration, undefined, axiosInstance);
},
inject: [ConfigService, REQUEST],
},
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { ICurrentUser } from '@infra/auth-guard';
import { BoardsClientAdapter, ColumnResponse } from '@infra/boards-client';
import { CardClientAdapter, CardControllerCreateElement201Response } from '@infra/cards-client';
import { ColumnClientAdapter } from '@infra/column-client';
import { CoursesClientAdapter } from '@infra/courses-client';
import { FilesStorageClientAdapter } from '@infra/files-storage-client';
import { Injectable } from '@nestjs/common';
import { CommonCartridgeFileParser } from '../import/common-cartridge-file-parser';
import {
Expand All @@ -11,8 +13,6 @@ import {
DEFAULT_FILE_PARSER_OPTIONS,
} from '../import/common-cartridge-import.types';
import { CommonCartridgeImportMapper } from './common-cartridge-import.mapper';
import { FilesStorageClientAdapter } from '@infra/files-storage-client';
import { ICurrentUser } from '@infra/auth-guard';

const DEPTH_BOARD = 0;
const DEPTH_COLUMN = 1;
Expand All @@ -21,6 +21,22 @@ const DEPTH_CARD_ELEMENTS = 3;

const DEFAULT_NEW_COURSE_COLOR = '#455B6A';

// Retry-Wrapper
async function retry<T>(fn: () => Promise<T>, retries = 5, delayMs = 500): Promise<T> {
let lastError: unknown;
for (let attempt = 0; attempt < retries; attempt++) {
try {
return await fn();
} catch (err) {
lastError = err;
// Optional: Log für Debugging
// console.warn(`Retry attempt ${attempt + 1} failed:`, err);
await new Promise((resolve) => setTimeout(resolve, delayMs * (attempt + 1)));
}
}
throw lastError;
}

interface ColumnResource {
column: CommonCartridgeOrganizationProps;
isResourceColumn: boolean;
Expand Down Expand Up @@ -60,6 +76,7 @@ export class CommonCartridgeImportService {

// INFO: for await keeps the order of the boards in the same order as the parser.getOrganizations()
// with Promise.all, the order of the boards would be random
const createdBoardIds = new Map<string, string>();
for await (const board of boards) {
const response = await this.boardsClient.createBoard({
title: board.title,
Expand All @@ -68,7 +85,15 @@ export class CommonCartridgeImportService {
parentType: 'course',
});

await this.createColumns(response.id, board, parser, currentUser);
createdBoardIds.set(board.identifier, response.id);
}

for await (const board of boards) {
const responseId = createdBoardIds.get(board.identifier);

if (!responseId) continue;

await this.createColumns(responseId, board, parser, currentUser);
}
}

Expand Down Expand Up @@ -105,7 +130,7 @@ export class CommonCartridgeImportService {
columnProps: CommonCartridgeOrganizationProps,
currentUser: ICurrentUser
): Promise<void> {
const columnResponse = await this.boardsClient.createBoardColumn(boardId);
const columnResponse = await retry(() => this.boardsClient.createBoardColumn(boardId));
await this.columnClient.updateBoardColumnTitle(columnResponse.id, { title: columnProps.title });

await this.createCardElementWithResource(parser, columnResponse, columnProps, currentUser);
Expand All @@ -117,7 +142,7 @@ export class CommonCartridgeImportService {
columnProps: CommonCartridgeOrganizationProps,
currentUser: ICurrentUser
): Promise<void> {
const columnResponse = await this.boardsClient.createBoardColumn(boardId);
const columnResponse = await retry(() => this.boardsClient.createBoardColumn(boardId));
await this.columnClient.updateBoardColumnTitle(columnResponse.id, { title: columnProps.title });

const cards = parser
Expand All @@ -139,7 +164,7 @@ export class CommonCartridgeImportService {
cardProps: CommonCartridgeOrganizationProps,
currentUser: ICurrentUser
): Promise<void> {
const card = await this.columnClient.createCard(columnResponse.id, {});
const card = await retry(() => this.columnClient.createCard(columnResponse.id, {}));

await this.createCardElement(parser, card.id, cardProps, currentUser);
}
Expand All @@ -150,7 +175,7 @@ export class CommonCartridgeImportService {
cardProps: CommonCartridgeOrganizationProps,
currentUser: ICurrentUser
): Promise<void> {
const card = await this.columnClient.createCard(column.id, {});
const card = await retry(() => this.columnClient.createCard(column.id, {}));
await this.cardClient.updateCardTitle(card.id, {
title: cardProps.title,
});
Expand Down Expand Up @@ -188,9 +213,11 @@ export class CommonCartridgeImportService {

if (!resourceBody) return;

const contentElement = await this.cardClient.createCardElement(cardId, {
type: contentElementType,
});
const contentElement = await retry(() =>
this.cardClient.createCardElement(cardId, {
type: contentElementType,
})
);

if (resource.type === 'file' || resource.type === 'fileFolder') {
await this.uploadFiles(currentUser, resource, contentElement);
Expand Down
Loading