Skip to content

Commit

Permalink
feat(SDACaseStudyFeature): first working version of the backend
Browse files Browse the repository at this point in the history
  • Loading branch information
alebg committed Nov 21, 2024
1 parent 3ce7bd4 commit 199d3b4
Show file tree
Hide file tree
Showing 8 changed files with 148 additions and 42 deletions.
10 changes: 3 additions & 7 deletions src/app/_components/dummy-case-study-enter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,17 +17,14 @@ export function DummyCaseStudyEnter() {
mutationKey: ["trigger-case-study"],
retry: DEFAULT_RETRIES,
retryDelay: DEFAULT_RETRY_DELAY,
onSuccess: async () => {
alert("Processed!");
},
mutationFn: caseStudyMutation(setCaseStudyViewModel),
});

function onSubmitHandlerForMutation() {
createMutation.mutate({
caseStudyName: "climate-monitoring",
tracerID: "test",
jobID: 1,
caseStudyName: "sentinel-5p",
tracerID: "potato",
jobID: 4,
});
}

Expand All @@ -53,7 +50,6 @@ export function DummyCaseStudyEnter() {
{caseStudyViewModel.status === "progress" && <div>Processing...</div>}

{caseStudyViewModel.status === "request" && <div>Waiting for request...</div>}

</div>
);
}
6 changes: 3 additions & 3 deletions src/lib/core/usecase/case-study-usecase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export default class BrowserCaseStudyUsecase implements CaseStudyInputPort {
const { caseStudyName, tracerID, jobID } = request;

// Ensure that the case study name is one of the two we support
if (caseStudyName !== "climate-monitoring" && caseStudyName !== "disaster-tracking") {
if (caseStudyName !== "climate-monitoring" && caseStudyName !== "sentinel-5p") {
this.presenter.presentError({
status: "error",
operation: "usecase#case-study",
Expand Down Expand Up @@ -236,12 +236,12 @@ export default class BrowserCaseStudyUsecase implements CaseStudyInputPort {
return;
}

const metadata: TCaseStudyMetadataWithoutRelativePaths = {
const metadata = {
caseStudy,
keyframes: keyframes,
imageKinds: imageKinds,
expirationTime,
};
} as TCaseStudyMetadataWithoutRelativePaths;

// 5. Prepare the agent source data
// If the Research Context was found already, we return it with a conversation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,42 @@ export default class BrowserConversationGateway implements ConversationGatewayOu
}

async createConversation(researchContextID: number, conversationTitle: string): Promise<CreateConversationDTO> {
return {
success: false,
data: {
operation: "browser#conversation#create",
message: "Method deprecated",
},
};
try {
const dto = await this.api.gateways.conversation.create.mutate({
researchContextID,
title: conversationTitle,
});
return dto;
} catch (error) {
this.logger.error({ error }, "Could not invoke the server side feature to create conversation");

return {
success: false,
data: {
operation: "browser#conversation#create-conversation",
message: "Could not invoke the server side feature to create conversation",
},
};
}
}

async listConversations(researchContextID: number): Promise<ListConversationsDTO> {
return {
success: false,
data: {
operation: "browser#conversation#list-conversations",
message: "Method deprecated",
},
};
try {
const dto = await this.api.gateways.conversation.list.query({
researchContextID,
});
return dto;
} catch (error) {
this.logger.error({ error }, "Could not invoke the server side feature to list conversations");

return {
success: false,
data: {
operation: "browser#conversation#list-conversations",
message: "Could not invoke the server side feature to list conversations",
},
};
}
}

async sendMessageToConversation(conversationID: number, message: TMessage): Promise<SendMessageToConversationResponseDTO> {
Expand All @@ -59,6 +78,7 @@ export default class BrowserConversationGateway implements ConversationGatewayOu
}

async listMessagesForConversation(conversationID: number): Promise<ListMessagesForConversationDTO> {
this.logger.error("Browser Conversation Gateway: listMessagesForConversation method deprecated");
return {
success: false,
data: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ export default class BrowserKernelSourceDataGateway implements KernelPlancksterS
}

async listSourceDataForResearchContext(researchContextID: number): Promise<ListSourceDataDTO> {
this.logger.error("Browser Source Data Gateway: listSourceDataForResearchContext method deprecated");
return {
success: false,
data: {
Expand All @@ -249,13 +250,19 @@ export default class BrowserKernelSourceDataGateway implements KernelPlancksterS
}

async listSourceDataForClient(): Promise<ListSourceDataDTO> {
return {
success: false,
data: {
operation: "browser#source-data#list",
message: `Method deprecated`,
},
};
try {
const dto = await this.api.gateways.sourceData.listSourceDataForClient.query();
return dto;
} catch (error) {
this.logger.error({ error }, "Could not invoke the server side feature to get client data for download");
return {
success: false,
data: {
operation: "sourceDataRouter#list",
message: "Could not invoke the server side feature to get client data for download",
},
};
}
}

async get(fileID: string): Promise<GetSourceDataDTO> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { GATEWAYS, UTILS } from "../config/ioc/server-ioc-symbols";
import { GetCaseStudyMetadataDTO } from "~/lib/core/dto/case-study-repository-dto";
import { RemoteFile } from "~/lib/core/entity/file";
import fs from "fs";
import { ClimateRowSchema, ErrorSchema, ImageSchema, SentinelRowSchema, TCaseStudyMetadata, TClimateKeyframe, TError, TImage, TKeyframeArray, TSentinelKeyframe } from "~/lib/core/entity/case-study-models";
import { ClimateRowSchema, ErrorSchema, SentinelRowSchema, TCaseStudyMetadata, TClimateKeyframe, TError, TImage, TKeyframeArray, TSentinelKeyframe } from "~/lib/core/entity/case-study-models";
import type KernelPlancksterSourceDataOutputPort from "../../common/ports/secondary/kernel-planckster-source-data-output-port";
import { SDACaseStudyMetadataSchema, TSDAKeyframe, TSDACaseStudyMetadata, generateMetadataRelativePath } from "../utils/sda-case-study-utils";
import { SDACaseStudyMetadataSchema, TSDAKeyframe, TSDACaseStudyMetadata, generateMetadataRelativePath, SDAImageSchema } from "../utils/sda-case-study-utils";

@injectable()
export default class SDACaseStudyRepository implements CaseStudyRepositoryOutputPort {
Expand Down Expand Up @@ -57,7 +57,7 @@ export default class SDACaseStudyRepository implements CaseStudyRepositoryOutput
const rawMetadataParseResult = SDACaseStudyMetadataSchema.safeParse(JSON.parse(rawContent.toString()));

if (!rawMetadataParseResult.success) {
this.logger.error({ metadata: rawContent.toString() }, "Failed to parse metadata.");
this.logger.error({ rawMetadataParseResult }, "Failed to parse metadata.");
return {
success: false,
data: {
Expand Down Expand Up @@ -95,7 +95,7 @@ export default class SDACaseStudyRepository implements CaseStudyRepositoryOutput

for (const singleRawImage of rawImages) {
const errorImageParseResult = ErrorSchema.safeParse(singleRawImage);
const metadataImageParseResult = ImageSchema.safeParse(singleRawImage);
const metadataImageParseResult = SDAImageSchema.safeParse(singleRawImage);

if (errorImageParseResult.success) {
parsedImages.push(errorImageParseResult.data);
Expand All @@ -119,7 +119,7 @@ export default class SDACaseStudyRepository implements CaseStudyRepositoryOutput
});
}
} else {
this.logger.error({ imageDatum: singleRawImage }, "Failed to parse image metadata.");
this.logger.error({ errorImageParseResult, metadataImageParseResult }, "Failed to parse image metadata.");
throw new Error("Failed to parse image metadata.");
}
}
Expand Down Expand Up @@ -150,7 +150,7 @@ export default class SDACaseStudyRepository implements CaseStudyRepositoryOutput

for (const singleRawImage of rawImages) {
const errorImageParseResult = ErrorSchema.safeParse(singleRawImage);
const metadataImageParseResult = ImageSchema.safeParse(singleRawImage);
const metadataImageParseResult = SDAImageSchema.safeParse(singleRawImage);

if (errorImageParseResult.success) {
parsedImages.push(errorImageParseResult.data);
Expand All @@ -174,7 +174,7 @@ export default class SDACaseStudyRepository implements CaseStudyRepositoryOutput
});
}
} else {
this.logger.error({ imageDatum: singleRawImage }, "Failed to parse image metadata.");
this.logger.error({ errorImageParseResult, metadataImageParseResult }, "Failed to parse image metadata.");
throw new Error("Failed to parse image metadata.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import serverContainer from "../../../config/ioc/server-container";
import { type Logger } from "pino";
import { GATEWAYS, UTILS } from "../../../config/ioc/server-ioc-symbols";
import type KernelConversationGateway from "../../../gateway/kernel-conversation-gateway";
import { type SendMessageToConversationResponseDTO } from "~/lib/core/dto/conversation-gateway-dto";
import { type CreateConversationDTO, type ListConversationsDTO, type SendMessageToConversationResponseDTO } from "~/lib/core/dto/conversation-gateway-dto";
import { list } from "postcss";

export const conversationGatewayRouter = createTRPCRouter({
sendMessageToConversation: protectedProcedure
Expand Down Expand Up @@ -36,4 +37,59 @@ export const conversationGatewayRouter = createTRPCRouter({
};
}
}),

create: protectedProcedure
.input(
z.object({
researchContextID: z.number(),
title: z.string(),
}),
)
.mutation(async ({ input }): Promise<CreateConversationDTO> => {
const loggerFactory = serverContainer.get<(module: string) => Logger>(UTILS.LOGGER_FACTORY);
const logger = loggerFactory("CreateConversation TRPC Router");

try {
const gateway = serverContainer.get<KernelConversationGateway>(GATEWAYS.KERNEL_CONVERSATION_GATEWAY);

const dto = await gateway.createConversation(input.researchContextID, input.title);

return dto;
} catch (error) {
logger.error({ error }, "Could not invoke the server side feature to create conversation");
return {
success: false,
data: {
operation: "conversationGatewayRouter#createConversation",
message: "Could not invoke the server side feature to create conversation",
},
};
}
}),

list: protectedProcedure
.input(
z.object({
researchContextID: z.number(),
}),
)
.query(async ({ input }): Promise<ListConversationsDTO> => {
const loggerFactory = serverContainer.get<(module: string) => Logger>(UTILS.LOGGER_FACTORY);
const logger = loggerFactory("ListConversations TRPC Router");

try {
const gateway = serverContainer.get<KernelConversationGateway>(GATEWAYS.KERNEL_CONVERSATION_GATEWAY);
const dto = await gateway.listConversations(input.researchContextID);
return dto;
} catch (error) {
logger.error({ error }, "Could not invoke the server side feature to list conversations");
return {
success: false,
data: {
operation: "conversationGatewayRouter#list",
message: "Could not invoke the server side feature to list conversations",
},
};
}
}),
});
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { type Logger } from "pino";
import { GATEWAYS, UTILS } from "../../../config/ioc/server-ioc-symbols";
import type KernelSourceDataGateway from "../../../gateway/kernel-source-data-gateway";
import { type GetClientDataForDownloadDTO, type GetClientDataForUploadDTO, type NewSourceDataDTO } from "~/lib/infrastructure/common/dto/kernel-planckster-source-data-gateway-dto";
import { type ListSourceDataDTO } from "~/lib/core/dto/source-data-gateway-dto";

export const sourceDataGatewayRouter = createTRPCRouter({
getClientDataForUpload: protectedProcedure
Expand Down Expand Up @@ -97,4 +98,24 @@ export const sourceDataGatewayRouter = createTRPCRouter({
};
}
}),

listSourceDataForClient: protectedProcedure.query(async (): Promise<ListSourceDataDTO> => {
const loggerFactory = serverContainer.get<(module: string) => Logger>(UTILS.LOGGER_FACTORY);
const logger = loggerFactory("ListSourceDataForClient TRPC Router");

try {
const gateway = serverContainer.get<KernelSourceDataGateway>(GATEWAYS.KERNEL_SOURCE_DATA_GATEWAY);
const dto = await gateway.listSourceDataForClient();
return dto;
} catch (error) {
logger.error({ error }, "Could not invoke the server side feature to get client data for download");
return {
success: false,
data: {
operation: "sourceDataGatewayRouter#listSourceDataForClient",
message: "Could not invoke the server side feature to get client data for download",
},
};
}
}),
});
12 changes: 9 additions & 3 deletions src/lib/infrastructure/server/utils/sda-case-study-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const caseStudyToSchema: Record<TRegisteredSDACaseStudyName, TRowSchema>
"sentinel-5p": SentinelRowSchema,
};

const SDAImageSchema = ImageSchema.omit({
export const SDAImageSchema = ImageSchema.omit({
signedUrl: true,
});

Expand All @@ -32,7 +32,10 @@ const SDAClimateKeyframeSchema = ClimateKeyframeSchema.omit({ images: true }).ex
images: z.array(SDAImageSchema),
});

const SDAClimateMetadataSchema = ClimateMetadataSchema.omit({ keyframes: true }).extend({
const SDAClimateMetadataSchema = ClimateMetadataSchema.omit({
keyframes: true,
expirationTime: true,
}).extend({
keyframes: z.array(SDAClimateKeyframeSchema),
relativePathsForAgent: z.array(z.string()),
});
Expand All @@ -45,7 +48,10 @@ const SDASentinelKeyframeSchema = SentinelKeyframeSchema.omit({ images: true }).
images: z.array(SDAImageSchema),
});

const SDASentinelMetadataSchema = SentinelMetadataSchema.omit({ keyframes: true }).extend({
const SDASentinelMetadataSchema = SentinelMetadataSchema.omit({
keyframes: true,
expirationTime: true,
}).extend({
keyframes: z.array(SDASentinelKeyframeSchema),
relativePathsForAgent: z.array(z.string()),
});
Expand Down

0 comments on commit 199d3b4

Please sign in to comment.