-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
8695bf3
commit 3653cb2
Showing
4 changed files
with
165 additions
and
0 deletions.
There are no files selected for viewing
76 changes: 76 additions & 0 deletions
76
packages/backend/src/peripherals/database/IndexerStateRepository.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { Logger } from '@l2beat/backend-tools' | ||
import { expect } from 'earl' | ||
|
||
import { setupDatabaseTestSuite } from '../../test/database' | ||
import { IndexerStateRepository } from './IndexerStateRepository' | ||
|
||
describe(IndexerStateRepository.name, () => { | ||
const { database } = setupDatabaseTestSuite() | ||
const repository = new IndexerStateRepository(database, Logger.SILENT) | ||
|
||
before(() => repository.deleteAll()) | ||
afterEach(() => repository.deleteAll()) | ||
|
||
it('adds single record and queries it', async () => { | ||
const record = { | ||
id: 'id', | ||
height: 1, | ||
} | ||
|
||
await repository.addOrUpdate(record) | ||
|
||
const actual = await repository.getAll() | ||
|
||
expect(actual).toEqual([record]) | ||
}) | ||
|
||
it('updates existing record', async () => { | ||
const record = { | ||
id: 'id', | ||
height: 1, | ||
} | ||
|
||
await repository.addOrUpdate(record) | ||
await repository.addOrUpdate({ ...record, height: 2 }) | ||
|
||
const actual = await repository.getAll() | ||
|
||
expect(actual).toEqual([{ ...record, height: 2 }]) | ||
}) | ||
|
||
it('finds record by id', async () => { | ||
const record = { | ||
id: 'id', | ||
height: 1, | ||
} | ||
|
||
const record2 = { | ||
id: 'id2', | ||
height: 2, | ||
} | ||
|
||
await repository.addOrUpdate(record) | ||
await repository.addOrUpdate(record2) | ||
|
||
const actual = await repository.findById('id2') | ||
|
||
expect(actual).toEqual(record2) | ||
}) | ||
|
||
it('delete all records', async () => { | ||
await repository.addOrUpdate({ | ||
id: 'id', | ||
height: 1, | ||
}) | ||
await repository.addOrUpdate({ | ||
id: 'id2', | ||
height: 2, | ||
}) | ||
|
||
await repository.deleteAll() | ||
|
||
const actual = await repository.getAll() | ||
|
||
expect(actual).toEqual([]) | ||
}) | ||
}) |
56 changes: 56 additions & 0 deletions
56
packages/backend/src/peripherals/database/IndexerStateRepository.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { Logger } from '@l2beat/backend-tools' | ||
import type { IndexerStateRow } from 'knex/types/tables' | ||
|
||
import { BaseRepository, CheckConvention } from './shared/BaseRepository' | ||
import { Database } from './shared/Database' | ||
|
||
export interface IndexerStateRecord { | ||
id: string // TODO: Maybe branded string? | ||
height: number | ||
} | ||
|
||
export class IndexerStateRepository extends BaseRepository { | ||
constructor(database: Database, logger: Logger) { | ||
super(database, logger) | ||
this.autoWrap<CheckConvention<IndexerStateRepository>>(this) | ||
} | ||
|
||
async addOrUpdate(record: IndexerStateRecord): Promise<string> { | ||
const row = toRow(record) | ||
const knex = await this.knex() | ||
await knex('indexer_states').insert(row).onConflict('id').merge() | ||
return record.id | ||
} | ||
|
||
async findById(id: string): Promise<IndexerStateRecord | undefined> { | ||
const knex = await this.knex() | ||
const row = await knex('indexer_states').where('id', id).first() | ||
return row && toRecord(row) | ||
} | ||
|
||
async getAll(): Promise<IndexerStateRecord[]> { | ||
const knex = await this.knex() | ||
const rows = await knex('indexer_states').select('*') | ||
return rows.map(toRecord) | ||
} | ||
|
||
async deleteAll(): Promise<number> { | ||
const knex = await this.knex() | ||
return knex('indexer_states').delete() | ||
} | ||
} | ||
|
||
function toRow(record: IndexerStateRecord): IndexerStateRow { | ||
return { | ||
id: record.id, | ||
height: record.height, | ||
last_updated: new Date(), | ||
} | ||
} | ||
|
||
function toRecord(row: IndexerStateRow): IndexerStateRecord { | ||
return { | ||
id: row.id, | ||
height: row.height, | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
packages/backend/src/peripherals/database/migrations/002_indexer_states.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
/* | ||
====== IMPORTANT NOTICE ====== | ||
DO NOT EDIT OR RENAME THIS FILE | ||
This is a migration file. Once created the file should not be renamed or edited, | ||
because migrations are only run once on the production server. | ||
If you find that something was incorrectly set up in the `up` function you | ||
should create a new migration file that fixes the issue. | ||
*/ | ||
|
||
import { Knex } from 'knex' | ||
|
||
export async function up(knex: Knex): Promise<void> { | ||
await knex.schema.createTable('indexer_states', (table) => { | ||
table.string('id').primary() | ||
table.integer('height').notNullable() | ||
table.dateTime('last_updated', { useTz: false }).notNullable() | ||
}) | ||
} | ||
|
||
export async function down(knex: Knex): Promise<void> { | ||
await knex.schema.dropTable('indexer_states') | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters