Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add more tests #298

Draft
wants to merge 4 commits into
base: feat/typeorm-store-cache
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,967 changes: 1,849 additions & 118 deletions common/config/rush/pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions typeorm/typeorm-store/Makefile
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
test:
@echo POSTGRES
@npx mocha -r dotenv/config lib/test/*.test.js --exit --timeout 5000
@npx jest --runInBand --runTestsByPath lib/test/*.test.js --forceExit
@echo COCKROACH
@DB_PORT=27437 npx mocha -r dotenv/config lib/test/*.test.js --exit --timeout 5000
@DB_PORT=27437 npx jest --runInBand TestsByPath lib/test/*.test.js --forceExit


up:
Expand Down
2 changes: 1 addition & 1 deletion typeorm/typeorm-store/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
postgres:
image: postgres:12
image: postgres:14
ports:
- "${DB_PORT_PG}:5432"
environment:
Expand Down
10 changes: 10 additions & 0 deletions typeorm/typeorm-store/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
testEnvironment: 'node',
setupFiles: ["dotenv/config"],
rootDir: ".",
transform: {
"^.+\\.ts$": "ts-jest"
},
// coverageReporters: ["html"]
};
13 changes: 8 additions & 5 deletions typeorm/typeorm-store/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
"main": "lib/index.js",
"scripts": {
"build": "rm -rf lib && tsc",
"test": "make up && sleep 1 && make test && make down || (make down && exit 1)"
"test": "make up && sleep 1 && make test && make down || (make down && exit 1)",
"cov": "jest --runInBand --runTestsByPath src/test/*.test.ts --forceExit --coverage"
},
"dependencies": {
"@subsquid/typeorm-config": "^4.1.1",
Expand All @@ -27,12 +28,14 @@
"@subsquid/big-decimal": "^1.0.0"
},
"devDependencies": {
"@types/mocha": "^10.0.6",
"dotenv": "16.4.5",
"@types/jest": "^27.4.0",
"@types/node": "^18.18.14",
"@types/pg": "^8.10.9",
"expect": "^29.7.0",
"mocha": "^10.2.0",
"ts-jest": "^29.1.4",
"jest": "^29.7.0",
"pg": "^8.11.3",
"typescript": "~5.3.2"
}
},
"packageManager": "[email protected]+sha1.7134f9b8d0b70bc7a1954f47af52123cd2b2acce"
}
8 changes: 4 additions & 4 deletions typeorm/typeorm-store/src/database.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export class TypeormDatabase {
constructor(options?: TypeormDatabaseOptions) {
this.statusSchema = options?.stateSchema || 'squid_processor'
this.isolationLevel = options?.isolationLevel || 'SERIALIZABLE'
this.resetMode = options?.resetMode || ResetMode.BATCH
this.resetMode = options?.resetMode || ResetMode.COMMIT
this.flushMode = options?.flushMode || FlushMode.AUTO
this.cacheMode = options?.cacheMode || CacheMode.ALL
this.supportsHotBlocks = options?.supportHotBlocks !== false
Expand Down Expand Up @@ -297,13 +297,13 @@ export class TypeormDatabase {
changes: changeWriter,
cacheMode: this.cacheMode,
flushMode: this.flushMode,
resetMode: this.resetMode,
})

try {
await cb(store)
await store.flush()
if (this.resetMode === ResetMode.BATCH) store.reset()
await store.flush(
this.resetMode === ResetMode.FLUSH || this.resetMode === ResetMode.COMMIT
)
} finally {
store['isClosed'] = true
}
Expand Down
63 changes: 36 additions & 27 deletions typeorm/typeorm-store/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ import assert from 'assert'
export {EntityTarget}

export const enum FlushMode {
/**
* Send queries to the database transaction whenever
* the data is read or written (including .get(),
* .insert(), .upsert(), .delete())
*/
IMMEDIATE,

/**
* Send queries to the database transaction at every
Expand All @@ -27,36 +33,28 @@ export const enum FlushMode {
AUTO,

/**
* Send queries to the database transaction strictly
* at the end of the batch.
* Send queries to the database strictly
* on the transaction commit.
*/
BATCH,

/**
* Send queries to the database transaction whenever
* the data is read or written (including .get(),
* .insert(), .upsert(), .delete())
*/
ALWAYS
COMMIT,
}

export const enum ResetMode {

/**
* Clear cache at the end of each batch or manually.
* Clear cache whenever any queries are sent to the
* database transaction.
*/
BATCH,
FLUSH,

/**
* Clear cache only manually.
* Clear state on the transaction commit.
*/
MANUAL,
COMMIT,

/**
* Clear cache whenever any queries are sent to the
* database transaction.
* Clear cache only manually.
*/
FLUSH
MANUAL,
}

export const enum CacheMode {
Expand Down Expand Up @@ -122,7 +120,7 @@ export interface StoreOptions {
changes?: ChangeWriter
logger?: Logger
flushMode: FlushMode
resetMode: ResetMode

cacheMode: CacheMode
}

Expand All @@ -136,19 +134,17 @@ export class Store {
protected logger?: Logger

protected flushMode: FlushMode
protected resetMode: ResetMode
protected cacheMode: CacheMode

protected pendingCommit?: Future<void>
protected isClosed = false

constructor({em, changes, logger, state, flushMode, resetMode, cacheMode}: StoreOptions) {
constructor({em, changes, logger, state, flushMode, cacheMode}: StoreOptions) {
this.em = em
this.changes = changes
this.logger = logger?.child('store')
this.state = state
this.flushMode = flushMode
this.resetMode = resetMode
this.cacheMode = cacheMode
}

Expand Down Expand Up @@ -305,10 +301,12 @@ export class Store {

async find<E extends EntityLiteral>(target: EntityTarget<E>, options: FindManyOptions<E>): Promise<E[]> {
return await this.performRead(async () => {
const metadata = this.getEntityMetadata(target)

const {cache, ...opts} = options
const res = await this.em.find(target, opts)
if (cache ?? this.cacheMode === CacheMode.ALL) {
const metadata = this.getEntityMetadata(target)

for (const e of res) {
this.cacheEntity(metadata, e)
}
Expand Down Expand Up @@ -365,6 +363,10 @@ export class Store {
return res
}

/**
* Get an entity by its id and put it in the cache.
* Subsequent calls to .get() with the same id will return the entity from the memory cache.
*/
async get<E extends EntityLiteral>(target: EntityTarget<E>, id: string): Promise<E | undefined>
async get<E extends EntityLiteral>(target: EntityTarget<E>, options: GetOptions<E>): Promise<E | undefined>
async get<E extends EntityLiteral>(
Expand All @@ -374,10 +376,17 @@ export class Store {
const {id, relations} = parseGetOptions(idOrOptions)
const metadata = this.getEntityMetadata(target)
let entity = this.state.get<E>(metadata, id, relations)
if (entity !== undefined) return noNull(entity)
if (entity !== undefined) {
return noNull(entity)
}

return await this.findOne(target, {where: {id} as any, relations, cache: true})
}

/**
* Get an entity by its id and put it in the cache or throw an error.
* Subsequent calls to .getOrFail() with the same id will return the entity from the memory cache.
*/
async getOrFail<E extends EntityLiteral>(target: EntityTarget<E>, id: string): Promise<E>
async getOrFail<E extends EntityLiteral>(target: EntityTarget<E>, options: GetOptions<E>): Promise<E>
async getOrFail<E extends EntityLiteral>(target: EntityTarget<E>, idOrOptions: string | GetOptions<E>): Promise<E> {
Expand Down Expand Up @@ -414,7 +423,7 @@ export class Store {
}
})

if (reset ?? this.resetMode === ResetMode.FLUSH) {
if (reset) {
this.reset()
}
} finally {
Expand All @@ -425,7 +434,7 @@ export class Store {

private async performRead<T>(cb: () => Promise<T>): Promise<T> {
this.assertNotClosed()
if (this.flushMode === FlushMode.AUTO || this.flushMode === FlushMode.ALWAYS) {
if (this.flushMode === FlushMode.AUTO || this.flushMode === FlushMode.IMMEDIATE) {
await this.flush()
}
return await cb()
Expand All @@ -435,7 +444,7 @@ export class Store {
this.assertNotClosed()
await this.pendingCommit?.promise()
await cb()
if (this.flushMode === FlushMode.ALWAYS) {
if (this.flushMode === FlushMode.IMMEDIATE) {
await this.flush()
}
}
Expand Down
1 change: 0 additions & 1 deletion typeorm/typeorm-store/src/test/database.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import expect from 'expect'
import {TypeormDatabase} from '../database'
import {Data} from './lib/model'
import {getEntityManager, useDatabase} from './util'
Expand Down
21 changes: 21 additions & 0 deletions typeorm/typeorm-store/src/test/lib/child.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Column, Entity, ManyToOne, PrimaryColumn } from 'typeorm';
import { Parent } from './parent';

@Entity()
export class Child {
@PrimaryColumn()
id!: string

@Column()
name?: string

@ManyToOne(() => Parent, parent => parent.children)
parent?: Parent

constructor(id?: string, name?: string) {
if (id != null) {
this.id = id
this.name = name
}
}
}
4 changes: 3 additions & 1 deletion typeorm/typeorm-store/src/test/lib/model.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {Column as Column_, Column, Entity, ManyToOne, PrimaryColumn} from 'typeorm'
import { Column as Column_, Column, Entity, ManyToOne, OneToMany, PrimaryColumn } from 'typeorm';

export * from './child'
export * from './parent'

@Entity()
export class Item {
Expand Down
21 changes: 21 additions & 0 deletions typeorm/typeorm-store/src/test/lib/parent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Column, Entity, OneToMany, PrimaryColumn } from 'typeorm';
import { Child } from './child';

@Entity()
export class Parent {
@PrimaryColumn()
id!: string

@Column()
name?: string

@OneToMany(() => Child, item => item.parent)
children?: Child[]

constructor(id?: string, name?: string) {
if (id != null) {
this.id = id
this.name = name
}
}
}
Loading