Skip to content

Commit

Permalink
Introduce seeds auto discovery
Browse files Browse the repository at this point in the history
  • Loading branch information
wcalderipe committed Feb 19, 2024
1 parent 6d7a834 commit 29b3478
Show file tree
Hide file tree
Showing 9 changed files with 194 additions and 94 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { Module } from '@nestjs/common'
import { PrismaService } from './service/prisma.service'
import { SeederService } from './service/seeder.service'
import { TestPrismaService } from './service/test-prisma.service'

@Module({
exports: [PrismaService, TestPrismaService],
providers: [PrismaService, TestPrismaService]
exports: [PrismaService, TestPrismaService, SeederService],
providers: [PrismaService, TestPrismaService, SeederService]
})
export class PersistenceModule {}
10 changes: 3 additions & 7 deletions apps/orchestration/src/shared/module/persistence/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ import { NestFactory } from '@nestjs/core'
import { Organization, PrismaClient } from '@prisma/client/orchestration'
import { ORGANIZATION } from 'packages/authz-shared/src/lib/dev.fixture'
import { OrchestrationModule } from '../../../orchestration.module'
import { EntityStoreSeed } from '../../../store/entity/persistence/entity-store.seed'
import { germinate as germinateTransferTrackingModule } from '../../../transfer-tracking/persistence/transfer.seed'
import { SeederService } from './service/seeder.service'

const now = new Date()
const prisma = new PrismaClient()
Expand All @@ -24,7 +23,7 @@ async function main() {
//
// See https://docs.nestjs.com/standalone-applications
const application = await NestFactory.createApplicationContext(OrchestrationModule)
const entityStoreSeed = application.get<EntityStoreSeed>(EntityStoreSeed)
const seeder = application.get<SeederService>(SeederService)

logger.log('Seeding Orchestration database')

Expand All @@ -36,11 +35,8 @@ async function main() {
}

try {
await entityStoreSeed.germinate()
// TODO (@wcalderipe, 15/02/24): Refactor to a seeder provider like entity store.
await germinateTransferTrackingModule(prisma)

logger.log('Orchestration database germinated 🌱')
await seeder.seed()
} finally {
await application.close()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Injectable } from '@nestjs/common'
import { Test } from '@nestjs/testing'
import { SeedService } from '../../seed.service'
import { SeederService } from '../../seeder.service'

@Injectable()
class TestSeedServiceOne extends SeedService {
override async germinate(): Promise<void> {}
}

@Injectable()
class TestSeedServiceTwo extends SeedService {
override async germinate(): Promise<void> {}
}

describe(SeederService.name, () => {
let service: SeederService
let seedServiceOne: TestSeedServiceOne
let seedServiceTwo: TestSeedServiceTwo

beforeEach(async () => {
seedServiceOne = new TestSeedServiceOne()
seedServiceTwo = new TestSeedServiceTwo()

const module = await Test.createTestingModule({
providers: [
SeederService,
{
provide: TestSeedServiceOne,
useValue: seedServiceOne
},
{
provide: TestSeedServiceTwo,
useValue: seedServiceTwo
}
]
}).compile()

service = module.get<SeederService>(SeederService)
})

describe('seed', () => {
it('discovers providers instance of SeedService and calls their germinate method', async () => {
jest.spyOn(seedServiceOne, 'germinate')
jest.spyOn(seedServiceTwo, 'germinate')

await service.seed()

expect(seedServiceOne.germinate).toHaveBeenCalledTimes(1)
expect(seedServiceTwo.germinate).toHaveBeenCalledTimes(1)
})
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { NotImplementedException } from '@nestjs/common'

export abstract class SeedService {
germinate(): Promise<void> {
throw new NotImplementedException()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Inject, Injectable, Logger } from '@nestjs/common'
import { ModulesContainer } from '@nestjs/core'
import { SeedService } from './seed.service'

@Injectable()
export class SeederService {
private logger = new Logger(SeedService.name)

constructor(@Inject(ModulesContainer) private modulesContainer: ModulesContainer) {}

async seed() {
for (const seed of this.getSeedServices()) {
const name = seed.constructor.name

this.logger.log(`Germinating ${name}`)

let error: unknown | null = null
try {
await seed.germinate()
} catch (err) {
this.logger.error('Error while germinating ${name}')

error = err
}

if (!error) {
this.logger.log(`${name} germinated`)
}
}
}

private getSeedServices(): SeedService[] {
return Array.from(this.modulesContainer.values())
.flatMap((module) => Array.from(module.providers.values()))
.map((provider) => provider.instance)
.filter((instance): instance is SeedService => instance instanceof SeedService)
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { FIXTURE } from '@narval/authz-shared'
import { Injectable, Logger } from '@nestjs/common'
import { Injectable } from '@nestjs/common'
import { compact } from 'lodash/fp'
import { ORGANIZATION } from 'packages/authz-shared/src/lib/dev.fixture'
import { Seeder } from '../../../shared/module/persistence/persistence.type'
import { SeedService } from '../../../shared/module/persistence/service/seed.service'
import { AddressBookRepository } from './repository/address-book.repository'
import { CredentialRepository } from './repository/credential.repository'
import { TokenRepository } from './repository/token.repository'
Expand All @@ -13,9 +13,7 @@ import { WalletGroupRepository } from './repository/wallet-group.repository'
import { WalletRepository } from './repository/wallet.repository'

@Injectable()
export class EntityStoreSeed implements Seeder {
private logger = new Logger(EntityStoreSeed.name)

export class EntityStoreSeed extends SeedService {
constructor(
private addressBookRepository: AddressBookRepository,
private credentialRepository: CredentialRepository,
Expand All @@ -25,11 +23,11 @@ export class EntityStoreSeed implements Seeder {
private userWalletRepository: UserWalletRepository,
private walletGroupRepository: WalletGroupRepository,
private walletRepository: WalletRepository
) {}

async germinate(): Promise<void> {
this.logger.log('Germinating the Entity Store module database')
) {
super()
}

override async germinate(): Promise<void> {
await Promise.all(
Object.values(FIXTURE.USER).map((entity) => this.userRepository.create(FIXTURE.ORGANIZATION.uid, entity))
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { Injectable } from '@nestjs/common'
import { getTime, subHours } from 'date-fns'
import { POLYGON } from '../../orchestration.constant'
import { PrismaService } from '../../shared/module/persistence/service/prisma.service'
import { SeedService } from '../../shared/module/persistence/service/seed.service'

@Injectable()
export class TransferTrackingSeed extends SeedService {
constructor(private prismaService: PrismaService) {
super()
}

override async germinate(): Promise<void> {
const now = getTime(new Date())
const twentyHoursAgo = subHours(now, 20)
const orgId = '7d704a62-d15e-4382-a826-1eb41563043b'
const rates = {
'fiat:usd': '0.99',
'fiat:eur': '1.10'
}

// TODO (@wcalderipe, 19/02/24): Refactor to use the repository instead of
// writing directly through the model.
await this.prismaService.approvedTransfer.createMany({
data: [
{
orgId,
rates,
id: '107b07ec-3e8d-440f-9e4a-d145dcd53324',
requestId: '623121f4-439c-42ac-aee3-d38f94f6f886',
amount: '3000000000',
from: 'eip155:137:0x90d03a8971a2faa19a9d7ffdcbca28fe826a289b',
to: 'eip155:137:0x08a08d0504d4f3363a5b7fda1f5fff1c7bca8ad4',
chainId: 137,
token: POLYGON.coin.id,
initiatedBy: 'matt@narval.xyz',
createdAt: twentyHoursAgo
},
{
orgId,
rates,
id: '2b697c4b-4675-4762-b68d-89baaa1b5cb8',
requestId: 'e615f495-fa7b-4ee8-b4c6-927ce72a9107',
amount: '2000000000',
from: 'eip155:137:0x90d03a8971a2faa19a9d7ffdcbca28fe826a289b',
to: 'eip155:137:0x08a08d0504d4f3363a5b7fda1f5fff1c7bca8ad4',
chainId: 137,
token: POLYGON.coin.id,
initiatedBy: 'matt@narval.xyz',
createdAt: twentyHoursAgo
},
{
orgId,
rates,
id: '4810c9de-ebc6-4788-ba5c-e9a899273c86',
requestId: '1d88e7e4-49ab-4f83-9e55-c3e089a4a252',
amount: '1500000000',
from: 'eip155:137:0x90d03a8971a2faa19a9d7ffdcbca28fe826a289b',
to: 'eip155:137:0x08a08d0504d4f3363a5b7fda1f5fff1c7bca8ad4',
chainId: 137,
token: POLYGON.coin.id,
initiatedBy: 'matt@narval.xyz',
createdAt: twentyHoursAgo
},
{
orgId,
rates,
id: 'a8116490-2c0e-4315-892f-f4795ff7eda9',
requestId: 'c91393e3-1cbb-49e6-888c-50f188f22f7e',
amount: '1000000000',
from: 'eip155:137:0x90d03a8971a2faa19a9d7ffdcbca28fe826a289b',
to: 'eip155:137:0x08a08d0504d4f3363a5b7fda1f5fff1c7bca8ad4',
chainId: 137,
token: POLYGON.coin.id,
initiatedBy: 'matt@narval.xyz',
createdAt: twentyHoursAgo
}
]
})
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ import { Module } from '@nestjs/common'
import { PersistenceModule } from '../shared/module/persistence/persistence.module'
import { TransferTrackingService } from './core/service/transfer-tracking.service'
import { TransferRepository } from './persistence/repository/transfer.repository'
import { TransferTrackingSeed } from './persistence/transfer-tracking.seed'

@Module({
imports: [PersistenceModule],
providers: [TransferRepository, TransferTrackingService],
providers: [TransferRepository, TransferTrackingService, TransferTrackingSeed],
exports: [TransferTrackingService]
})
export class TransferTrackingModule {}

0 comments on commit 29b3478

Please sign in to comment.