Feature/persistent solvers store - #154
Open
Keengfk wants to merge 4 commits into
Open
Conversation
- Add Prisma 5.22.0 (prisma + @prisma/client) as dependencies - Add prisma/schema.prisma with Intent, Solver, Token models and IntentState / SupportedChain enums; all fields indexed appropriately - Add initial migration SQL (prisma/migrations/20240101000000_init/) - Add PrismaService (extends PrismaClient, NestJS lifecycle hooks) and global PrismaModule; wire into AppModule - Add DATABASE_URL to Joi validation schema, AppConfig, and .env.example - Add npm scripts: db:generate, db:migrate, db:migrate:prod, db:studio, db:validate - Update Dockerfile: build stage runs prisma generate; runtime CMD runs prisma migrate deploy before starting the server - Update CI: add postgres:16-alpine service container and migration steps (db:validate, db:generate, db:migrate:prod) before build/test - Add PrismaService unit test (src/prisma/prisma.service.spec.ts) - Mock PrismaService in e2e test helper so suites stay DB-free Closes stellar-vortex-protocol#37
- Add IIntentsRepository interface (save, findById, findAll, findByState, findByUser, update) and INTENTS_REPOSITORY Symbol token in src/intents/intents.repository.ts - Add InMemoryIntentsRepository in src/intents/in-memory-intents.repository.ts — lifts all Map logic and seed data out of IntentsService - Refactor IntentsService to pure orchestration: UUID generation, default state/deadline live here; all persistence delegated to the injected IIntentsRepository - Update IntentsModule to bind InMemoryIntentsRepository under the INTENTS_REPOSITORY token — swap the binding to change storage backend - Update intents.service.spec.ts to wire service via TestingModule with real InMemoryIntentsRepository under the DI token - Add in-memory-intents.repository.spec.ts — 14 tests covering every method including seed, overwrite, case-insensitive user lookup, and partial-patch behaviour All tests pass: 35 unit (5 suites), 23 e2e (5 suites), lint clean, typecheck clean. Closes stellar-vortex-protocol#38
- Add DatabaseHealthService: probes via PrismaService.$queryRaw`SELECT 1`,
races against a 3s timeout, never throws, returns
{ status, latencyMs?, error? }
- Update HealthController: async check(), injects DatabaseHealthService,
response includes a top-level `db` field
- Update HealthModule: provide DatabaseHealthService (PrismaModule is
already global so no import needed)
- Update health.e2e-spec.ts: assert db field shape for both the ok and
unreachable branches — suite passes with the mock PrismaService that
has no real connection, exercising the graceful-degradation path
- Add database-health.service.spec.ts: 4 unit tests covering the success
path, query rejection, timeout (fake timers), and missing $queryRaw
Closes stellar-vortex-protocol#39
Extract ISolversRepository interface and InMemorySolversRepository adapter from SolversService, following the same pattern established for intents (refactor/intents-repository-interface). - Add ISolversRepository interface (save, findByAddress, findAll) and SOLVERS_REPOSITORY Symbol token in src/solvers/solvers.repository.ts - Add InMemorySolversRepository in src/solvers/in-memory-solvers.repository.ts — lifts all Map logic and seed data out of SolversService - Refactor SolversService to pure orchestration: counter initialisation and timestamp generation live here; all persistence delegated to the injected ISolversRepository - Update SolversModule to bind InMemorySolversRepository under the SOLVERS_REPOSITORY token — swap the binding to change storage backend - Update solvers.service.spec.ts to wire service via TestingModule with InMemorySolversRepository injected under the DI token; add registeredAt timestamp test - Add in-memory-solvers.repository.spec.ts — 10 tests covering seed, save/overwrite, findByAddress miss, findAll snapshot immutability All tests pass: 49 unit (7 suites), 23 e2e (5 suites), lint clean, typecheck clean. Closes stellar-vortex-protocol#40
|
@Keengfk Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Solver registrations, fill counts, and bond amounts currently live in a plain
Map inside SolversService and vanish on every restart. This PR extracts the
storage behind an ISolversRepository interface with an
InMemorySolversRepository as the first adapter, following the exact same
pattern established for intents in refactor/intents-repository-interface. The
in-memory behaviour is unchanged — this is purely a structural refactor that
makes the storage backend swappable so the Prisma adapter (issue #36) can be
plugged in without touching SolversService.
───────────────────────────────────────────────────────────────────────────────
Changes
src/solvers/solvers.repository.ts (new)
Defines the ISolversRepository interface (3 methods: save, findByAddress,
findAll) and the SOLVERS_REPOSITORY Symbol injection token.
src/solvers/in-memory-solvers.repository.ts (new)
The existing Map-based storage and seed logic lifted directly from
SolversService into an @Injectable() class that implements ISolversRepository.
Behaviour is identical — pure structural move.
src/solvers/solvers.service.ts (modified)
Stripped to pure orchestration: zeroed counters (fillsCompleted, fillsFailed,
totalVolume) and registeredAt timestamp are set here. All this.solvers.* calls
replaced with this.repo.* via the injected ISolversRepository. No logic added
or removed.
src/solvers/solvers.module.ts (modified)
Registers { provide: SOLVERS_REPOSITORY, useClass: InMemorySolversRepository }.
To swap to a Prisma-backed adapter, only this one binding changes.
───────────────────────────────────────────────────────────────────────────────
How to add a new storage adapter
// e.g. prisma-solvers.repository.ts
@Injectable()
export class PrismaSolversRepository implements ISolversRepository {
constructor(private readonly prisma: PrismaService) {}
// ... implement save, findByAddress, findAll
}
// solvers.module.ts — one line change:
{ provide: SOLVERS_REPOSITORY, useClass: PrismaSolversRepository }
───────────────────────────────────────────────────────────────────────────────
Testing
count and addresses, save persists and returns, overwrite keeps count stable,
count increments for new address, findByAddress miss/hit, findAll count,
snapshot immutability (mutating the returned array does not affect the store)
Test.createTestingModule with InMemorySolversRepository injected under the
token, matching production DI exactly; added registeredAt timestamp assertion
npm run lint ✓ 0 errors
npm run typecheck ✓ 0 errors
npm run build ✓ clean
npm test ✓ 49 tests, 7 suites (+10 new)
npm run test:e2e ✓ 23 tests, 5 suites
closes #55