Skip to content

Commit 4bd2cc2

Browse files
authored
Merge pull request #958 from Securify001/backend-stream
backend-stream
2 parents 4beb172 + 83de769 commit 4bd2cc2

5 files changed

Lines changed: 64 additions & 24 deletions

File tree

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
-- Replace the unused (streamId, createdAt) composite with (streamId, timestamp),
2+
-- which matches streamId-scoped event listings that ORDER BY timestamp.
3+
4+
-- CreateIndex
5+
CREATE INDEX IF NOT EXISTS "StreamEvent_streamId_timestamp_idx" ON "StreamEvent"("streamId", "timestamp");
6+
7+
-- DropIndex
8+
DROP INDEX IF EXISTS "StreamEvent_streamId_createdAt_idx";

backend/prisma/schema.prisma

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,5 +86,6 @@ model StreamEvent {
8686
@@index([timestamp])
8787
@@index([transactionHash])
8888
@@index([createdAt])
89-
@@index([streamId, createdAt])
89+
@@index([streamId, timestamp])
90+
@@unique([transactionHash, eventType])
9091
}

backend/tests/integration/streams.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,17 @@ describe('GET /v1/streams/:id/events — pagination and eventType filter', () =>
231231
expect(res.body).toHaveProperty('hasMore');
232232
expect(Array.isArray(res.body.data)).toBe(true);
233233
expect(res.body.hasMore).toBe(false);
234+
235+
const callArgs = mockPrisma.streamEvent.findMany.mock.calls[0]![0] as {
236+
where: { streamId: number };
237+
orderBy: { timestamp: string };
238+
take: number;
239+
skip: number;
240+
};
241+
expect(callArgs.where.streamId).toBe(1);
242+
expect(callArgs.orderBy).toEqual({ timestamp: 'desc' });
243+
expect(callArgs.take).toBe(10);
244+
expect(callArgs.skip).toBe(0);
234245
});
235246

236247
it('enforces default limit of 50', async () => {

backend/tests/stream.controller.test.ts

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,11 @@
1-
import { describe, it, expect, vi, beforeEach } from "vitest";
2-
import {
3-
createStream,
4-
listStreams,
5-
getStream,
6-
getStreamClaimableAmount,
7-
pauseStream,
8-
resumeStream,
9-
} from "../src/controllers/stream.controller.js";
10-
import { prisma } from "../src/lib/prisma.js";
11-
import { claimableAmountService } from "../src/services/claimable.service.js";
12-
import * as sorobanService from "../src/services/sorobanService.js";
13-
import type { Request, Response } from "express";
14-
15-
type TestRequest = Partial<Request> & {
16-
user?: {
17-
publicKey: string;
18-
};
19-
};
20-
21-
vi.mock("../src/lib/prisma.js", () => ({
1+
import { describe, it, expect, vi, beforeEach } from 'vitest';
2+
import { createStream, listStreams, getStream, getStreamEvents, getStreamClaimableAmount, pauseStream, resumeStream } from '../src/controllers/stream.controller.js';
3+
import { prisma } from '../src/lib/prisma.js';
4+
import { claimableAmountService } from '../src/services/claimable.service.js';
5+
import * as sorobanService from '../src/services/sorobanService.js';
6+
import type { Request, Response } from 'express';
7+
8+
vi.mock('../src/lib/prisma.js', () => ({
229
prisma: {
2310
stream: {
2411
upsert: vi.fn(),
@@ -29,6 +16,8 @@ vi.mock("../src/lib/prisma.js", () => ({
2916
},
3017
streamEvent: {
3118
create: vi.fn(),
19+
findMany: vi.fn(),
20+
count: vi.fn(),
3221
},
3322
},
3423
}));
@@ -235,8 +224,34 @@ describe("Stream Controller", () => {
235224
await getStream(req as Request, res as Response);
236225

237226
expect(res.status).toHaveBeenCalledWith(200);
238-
expect(res.json).toHaveBeenCalledWith(
239-
expect.objectContaining({ streamId: 123 }),
227+
expect(res.json).toHaveBeenCalledWith(expect.objectContaining({ streamId: 123 }));
228+
expect(prisma.stream.findUnique).toHaveBeenCalledWith(
229+
expect.objectContaining({
230+
include: expect.objectContaining({
231+
events: { orderBy: { timestamp: 'desc' } },
232+
}),
233+
}),
234+
);
235+
});
236+
});
237+
238+
describe('getStreamEvents', () => {
239+
it('should paginate stream events ordered by timestamp desc', async () => {
240+
req.params = { streamId: '123' };
241+
req.query = { limit: '10', offset: '0' };
242+
(prisma.streamEvent.findMany as any).mockResolvedValue([]);
243+
(prisma.streamEvent.count as any).mockResolvedValue(0);
244+
245+
await getStreamEvents(req as Request, res as Response);
246+
247+
expect(res.status).toHaveBeenCalledWith(200);
248+
expect(prisma.streamEvent.findMany).toHaveBeenCalledWith(
249+
expect.objectContaining({
250+
where: { streamId: 123 },
251+
orderBy: { timestamp: 'desc' },
252+
take: 10,
253+
skip: 0,
254+
}),
240255
);
241256
});
242257
});

backend/tests/user.controller.test.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,11 @@ describe('User Controller', () => {
167167
await getUserEvents(req as Request, res as Response, next);
168168

169169
expect(res.status).toHaveBeenCalledWith(200);
170+
expect(prisma.streamEvent.findMany).toHaveBeenCalledWith(
171+
expect.objectContaining({
172+
orderBy: { timestamp: 'desc' },
173+
}),
174+
);
170175
expect(res.json).toHaveBeenCalledWith(expect.objectContaining({
171176
data: [],
172177
total: 0,

0 commit comments

Comments
 (0)