Skip to content

Commit

Permalink
Refactor and remove in-memory event service
Browse files Browse the repository at this point in the history
  • Loading branch information
coocos committed Apr 7, 2021
1 parent cda313b commit 4867f76
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 194 deletions.
10 changes: 5 additions & 5 deletions src/controllers/eventController.ts → src/controllers/events.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import { Request, Response } from "express";
import logger from "../logger";
import { sqlEventService } from "../services/sqlEventService";
import { events } from "../services/events";

export async function listEvents(req: Request, res: Response): Promise<void> {
try {
const events = await sqlEventService.findAll();
const allEvents = await events.findAll();
res.json(
events.map(({ type, location, time }) => ({
allEvents.map(({ type, location, time }) => ({
type,
location,
time: time.toISOString(),
}))
);
} catch (e) {
logger.error(`Failed to list events: ${e}`);
} catch (err) {
logger.error(`Failed to list events: ${err.message}`);
res.status(500).json({
error: "failed to list events",
});
Expand Down
13 changes: 6 additions & 7 deletions src/poll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,19 @@ import cron from "node-cron";

import logger from "./logger";
import config from "./config";
import { sqlEventService } from "./services/sqlEventService";
import { fetchFeedEvents } from "./services/feedService";
import { RescueEvent } from "./services/eventService";
import { events, RescueEvent } from "./services/events";
import { fetchFeedEvents } from "./services/feed";

export const pollFeed = (
eventCallback: (event: RescueEvent) => void
): cron.ScheduledTask => {
const task = cron.schedule(config.feed.schedule, async () => {
try {
const events = await fetchFeedEvents();
for (const event of events) {
if (!(await sqlEventService.exists(event))) {
const feedEvents = await fetchFeedEvents();
for (const event of feedEvents) {
if (!(await events.exists(event))) {
logger.info("New event", event);
await sqlEventService.add(event);
await events.add(event);
eventCallback(event);
}
}
Expand Down
26 changes: 11 additions & 15 deletions src/routes/events.test.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,20 @@
import request from "supertest";
import app from "../app";
import { inMemoryEventService } from "../services/inMemoryEventService";
import { events } from "../services/events";

jest.mock("../services/sqlEventService", () => {
const { inMemoryEventService } = jest.requireActual(
"../services/inMemoryEventService"
);
return {
sqlEventService: inMemoryEventService,
};
});
jest.mock("../services/events");

describe("/events", () => {
it("returns list of events", async () => {
inMemoryEventService.add({
type: "rakennuspalo: keskisuuri",
location: "Tuusula",
time: new Date("2021-01-31T22:00:00.000Z"),
hash: "2a39407ee0570aae8f3ba2842e11aa28ce0f5d9f",
});
const mockEvents = events as jest.Mocked<typeof events>;
mockEvents.findAll.mockResolvedValue([
{
type: "rakennuspalo: keskisuuri",
location: "Tuusula",
time: new Date("2021-01-31T22:00:00.000Z"),
hash: "2a39407ee0570aae8f3ba2842e11aa28ce0f5d9f",
},
]);
const response = await request(app).get("/api/v1/events");
expect(response.status).toBe(200);
expect(response.body).toEqual([
Expand Down
2 changes: 1 addition & 1 deletion src/routes/events.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import express from "express";
import * as eventController from "../controllers/eventController";
import * as eventController from "../controllers/events";

const router = express.Router();

Expand Down
12 changes: 0 additions & 12 deletions src/services/eventService.ts

This file was deleted.

96 changes: 96 additions & 0 deletions src/services/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import db from "../db";
import logger from "../logger";

export type RescueEvent = {
type: string;
location: string;
time: Date;
hash: string;
};

type Location = {
id: number;
name: string;
};
type Type = {
id: number;
name: string;
};
type Event = {
id: number;
location_id: number;
type_id: number;
time: Date;
hash: string;
};

export const events = {
async findAll(): Promise<RescueEvent[]> {
const events = await db("events")
.join("types", "types.id", "events.type_id")
.join("locations", "locations.id", "events.location_id")
.select<RescueEvent[]>(
"events.time",
"events.hash",
"locations.name as location",
"types.name as type"
);
return events;
},
async exists(event: RescueEvent): Promise<boolean> {
const knownEvent = await db<Event>("events")
.select("*")
.where({ hash: event.hash })
.first();
return knownEvent !== undefined;
},
async add(event: RescueEvent): Promise<void> {
try {
return await db.transaction(async (trx) => {
const knownEvent = await trx<Event>("events")
.select("*")
.where({
hash: event.hash,
})
.first();
if (knownEvent !== undefined) {
return;
}
let location = await trx<Location>("locations")
.select("*")
.where({
name: event.location,
})
.first();
if (location === undefined) {
[location] = await trx("locations")
.insert({
name: event.location,
})
.returning<Location[]>("*");
}
let type = await trx<Type>("types")
.select("*")
.where({
name: event.type,
})
.first();
if (type === undefined) {
[type] = await trx("types")
.insert({
name: event.type,
})
.returning<Type[]>("*");
}
await trx("events").insert({
type_id: type.id,
location_id: location.id,
time: event.time,
hash: event.hash,
});
});
} catch (err) {
logger.error(err);
}
},
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import axios from "axios";
import { fetchFeedEvents } from "./feedService";
import { fetchFeedEvents } from "./feed";

jest.mock("axios");

Expand Down
2 changes: 1 addition & 1 deletion src/services/feedService.ts → src/services/feed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import hash from "object-hash";
import Parser from "rss-parser";

import config from "../config";
import { RescueEvent } from "./eventService";
import { RescueEvent } from "./events";

const cache = {
etag: "",
Expand Down
38 changes: 0 additions & 38 deletions src/services/inMemoryEventService.test.ts

This file was deleted.

21 changes: 0 additions & 21 deletions src/services/inMemoryEventService.ts

This file was deleted.

93 changes: 0 additions & 93 deletions src/services/sqlEventService.ts

This file was deleted.

0 comments on commit 4867f76

Please sign in to comment.