Skip to content

Commit

Permalink
Merge pull request #436 from 51ngul4r1ty/issue/000434/backlog-item-en…
Browse files Browse the repository at this point in the history
…dpoint-multi-project-fix

fix for backlog-item multi-project issue
  • Loading branch information
51ngul4r1ty authored Sep 18, 2022
2 parents ab476a7 + 697846d commit 308f213
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 32 deletions.
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "atoll",
"version": "0.62.0",
"version": "0.62.3",
"author": {
"name": "Kevin Berry",
"email": "[email protected]"
Expand Down Expand Up @@ -59,7 +59,7 @@
"check:prereqs": "ts-node ./scripts/check-prereqs.ts"
},
"dependencies": {
"@atoll/shared": "0.62.0",
"@atoll/shared": "0.62.3",
"@flopflip/memory-adapter": "1.6.0",
"@flopflip/react-broadcast": "10.1.11",
"axios": "0.26.1",
Expand Down
7 changes: 4 additions & 3 deletions src/server/api/handlers/backlogItemParts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ export const backlogItemPartPatchHandler = async (req: Request, res: Response) =
newDataItem,
originalApiBacklogItem,
res,
handlerContext.transactionContext.transaction
handlerContext
);
}
}
Expand Down Expand Up @@ -166,8 +166,9 @@ const handleResponseWithUpdatedStatsAndCommit = async (
newApiBacklogItem: ApiBacklogItem,
originalApiBacklogItem: ApiBacklogItem,
res: Response,
transaction: Transaction
handlerContext: HandlerContext
): Promise<void> => {
const transaction = handlerContext.transactionContext.transaction;
let sprintStats: ApiSprintStats;
const newBacklogItemPart = mapApiItemToBacklogItemPart(newApiBacklogItemPart);
const originalBacklogItemPart = mapApiItemToBacklogItemPart(originalApiBacklogItemPart);
Expand All @@ -191,7 +192,7 @@ const handleResponseWithUpdatedStatsAndCommit = async (
}
if (transaction) {
await transaction.commit();
transaction = null;
handlerContext.transactionContext.transaction = null;
}
const extra = sprintStats ? { sprintStats, backlogItem: newApiBacklogItem } : { backlogItem: newApiBacklogItem };
const meta = originalBacklogItemPart ? { original: originalBacklogItemPart } : undefined;
Expand Down
36 changes: 23 additions & 13 deletions src/server/api/handlers/fetchers/backlogItemFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import { FindOptions, Transaction } from "sequelize";

// libraries
import { ApiBacklogItem, LinkedList } from "@atoll/shared";
import type { ApiBacklogItem, ApiProductBacklogItem } from "@atoll/shared";
import { asyncForEach, LinkedList } from "@atoll/shared";

// data access
import { DB_INCLUDE_ALIAS_BACKLOGITEMPARTS } from "../../../dataaccess/models/dataModelConsts";
Expand Down Expand Up @@ -105,28 +106,37 @@ export const fetchBacklogItemsByDisplayId = async (
}
};

export const fetchBacklogItems = async (projectId: string): Promise<BacklogItemsResult | RestApiErrorResult> => {
if (!projectId) {
throw new Error("Unable to retrieve backlog items without specifying a projectId");
}
export const fetchBacklogItems = async (projectId: string | undefined): Promise<BacklogItemsResult | RestApiErrorResult> => {
try {
const params = { projectId };
const options = buildOptionsFromParams(params);
const dbProductBacklogItems = await ProductBacklogItemDataModel.findAll(options);
const rankList = new LinkedList<ApiBacklogItem>();
const productBacklogItemsByProjectId: { [projectId: string]: ApiProductBacklogItem[] } = {};
if (dbProductBacklogItems.length) {
const productBacklogItemsMapped = dbProductBacklogItems.map((item) => mapDbToApiProductBacklogItem(item));
productBacklogItemsMapped.forEach((item) => {
rankList.addInitialLink(item.backlogitemId, item.nextbacklogitemId);
if (!productBacklogItemsByProjectId[item.projectId]) {
productBacklogItemsByProjectId[item.projectId] = [];
}
productBacklogItemsByProjectId[item.projectId].push(item);
});
}
const backlogItemsOptions = buildBacklogItemFindOptionsForNested(params);
const dbBacklogItemsWithParts = await BacklogItemDataModel.findAll(backlogItemsOptions);
dbBacklogItemsWithParts.forEach((dbBacklogItemWithParts) => {
const result = buildApiItemFromDbItemWithParts(dbBacklogItemWithParts);
rankList.addItemData(result.id, result);
let combinedRankedLists: ApiBacklogItem[] = [];
await asyncForEach(Object.keys(productBacklogItemsByProjectId), async (projectId: string) => {
const projectBacklogItems = productBacklogItemsByProjectId[projectId];
const rankList = new LinkedList<ApiBacklogItem>();
projectBacklogItems.forEach((item) => {
rankList.addInitialLink(item.backlogitemId, item.nextbacklogitemId);
});
const backlogItemsOptions = buildBacklogItemFindOptionsForNested(params);
const dbBacklogItemsWithParts = await BacklogItemDataModel.findAll(backlogItemsOptions);
dbBacklogItemsWithParts.forEach((dbBacklogItemWithParts) => {
const result = buildApiItemFromDbItemWithParts(dbBacklogItemWithParts);
rankList.addItemData(result.id, result);
});
combinedRankedLists = combinedRankedLists.concat(rankList.toArray());
});
return buildResponseWithItems(rankList.toArray());
return buildResponseWithItems(combinedRankedLists);
} catch (error) {
return buildResponseFromCatchError(error, { includeStack: true });
}
Expand Down
14 changes: 7 additions & 7 deletions src/server/api/handlers/utils/handlerContext.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// externals
import { StatusCodes } from "http-status-codes";
import { Transaction } from "sequelize";
import { Response } from "express";
import type { Response } from "express";

// libraries
import { logger, LoggingContext } from "@atoll/shared";
Expand All @@ -19,22 +19,22 @@ import {
} from "../../utils/responder";
import { RestApiCollectionResult, RestApiErrorResult, RestApiItemResult } from "../../utils/responseBuilder";

export interface HandlerTransactionContext {
export type HandlerTransactionContext = {
transaction: Transaction;
aborted: boolean; // no further operations will be executed, but transaction has not been rolled back
rolledBack: boolean; // transaction has been rolled back, do not attempt to rollback again
}
};

export interface HandlerExpressContext {
export type HandlerExpressContext = {
res: Response;
}
};

export interface HandlerContext {
export type HandlerContext = {
logContext: LoggingContext;
functionTag: string;
expressContext: HandlerExpressContext;
transactionContext?: HandlerTransactionContext;
}
};

export const start = (functionTag: string, res: Response): HandlerContext => {
const logContext = logger.info("starting call", [functionTag]);
Expand Down

0 comments on commit 308f213

Please sign in to comment.