npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

typeorm-sharding-repository

v0.3.1

Published

TypeORM Sharding Repository: Enables TypeORM to be utilized in a distributed database environment.

Downloads

5

Readme

TypeORM Sharding Repository

  • TypeORM을 분산 데이터베이스 환경에서 활용할 수 있게 합니다.

Node.js CI NPM Version License

Install

  • NPM
$ npm install typeorm-sharding-repository --save
  • Yarn
$ yarn add typeorm-sharding-repository

Usage

1. Prepare DataSources.

  • TypeORM DataSource 설정 대신 ShardingManager을 설정해 주세요. 대부분의 설정은 TypeORM과 동일합니다.
  • 이 예제의 User entity는 정수형의 키를 가지고 있습니다. 호환되는 키나 키의 범위 규칙에 따라 ShardingManager를 설정하는 것을 추천합니다.
const dbConf = {
    host: 'localhost',
    database: 'playground',
    username: 'postgres',
    password: 'postgrespw',
    synchronize: true,
    logging: 'all',
};

const shardManager = await ShardingManager.init({
    shardingType: ShardingType.RANGE,
    // 이곳에 입력되는 공통 설정(TypeORM.BaseDataSourceOptions)은 모든 shard에 적용됩니다. 
    type: 'postgres',
    entities: [User],
    shards: [
        // 개별 데이터베이스 shard의 설정을 합니다.
        // minKey, maxKey는 다양한 타입을 가질수 있습니다. 멀티컬럼 PK를 가진 경우 튜플 형태로 구성할 수도 있습니다.
        // onInitialize(typeorm.DataSource) callback 은 옵션입니다.
        { ...dbConf, port: 55000, minKey: 0, maxKey: 1000, onInitialize: (dataSource) => {/* TypeORM.DataSource.initialize() 이후 실행됨 */} },
        { ...dbConf, port: 55001, minKey: 1000, maxKey: 2000, onInitialize: (dataSource) => {/**/} },
        { ...dbConf, port: 55002, minKey: 2000, maxKey: 3000, onInitialize: (dataSource) => {/**/} },
    ],
});

2. Apply to Entity

  1. @Entity decorator 대신 @ShardingEntity decorator를 사용하세요.
  2. BaseEntity 대신 ShardingBaseEntity를 상속받으세요.
  • 새로운 데이터가 추가된 shard에 쌓이기 시작합니다.
@ShardingEntity<User, number>({
    // Modular sharding은 추후 지원 예정입니다.
    type: ShardingType.RANGE,
    
    // Entity가 어떤 shard에서 처리될 지 알려줘야 합니다. 하나의 entity를 처리하기 위해 최대 shard 갯수만큼 호출됩니다.
    // 새로운 entity가 추가될 때에는 키 값이 비어있습니다.
    // 모든 shard에 대해 false가 리턴된 경우 마지막 샤드가 선택됩니다.
    // minKey, maxKey는 ShardingManager에 정의된 값들이 전달됩니다.
    // 여러 ShardingManager를 관리하고 싶지 않다면 이 함수에서 entity 간의 관계에 따라 minKey, maxKey를 기준으로만 삼고 데이터의 양을 조절할 수 있습니다.
    findShard: (entity: User, minKey, maxKey) => entity.id && minKey <= entity.id && entity.id < maxKey,
    
    // findShard과 유사하지만 판정을 entity가 아닌 키 값을 기준으로 합니다.
    // ID 값은 타입이 모호합니다. 이 예제에서는 number로 전달받았으나, 배열(멀티컬럼)이나 문자열 등 다양한 값이 전달되게 됩니다.
    // repository.findByIds() 등이 호출될 때 전달받는 ID 들이 전달되므로, 어떤 구조의 entity냐에 따라 전달되는 값의 형태가 달라지기 때문입니다.
    findShardById: (id: number, minKey, maxKey) => id && minKey <= id && id < maxKey,
})
export class User extends ShardingBaseEntity {
    @PrimaryGeneratedColumn() id: number;
    @Column() firstName: string;
    @Column() lastName: string;
    @Column() age: number;
}

3. RepositoryService (Abstract repository for TypeORM.BaseEntity and ShardingBaseEntity)

  • TypeORM.BaseEntity과 ShardingBaseEntity와 호횐되는 RepositoryService를 제공합니다.
  • 이 패턴을 활용할 경우 sharding 적용 여부를 변경하더라도 코드의 변경이 없습니다.
  • Repository Interface
// 두 저장소 서비스는 동일한 인터페이스를 가지고 있습니다. 
const typeormRepository = RepositoryService.of(MyEntityBasedOnTypeormBaseEntity);
const shardingRepository = RepositoryService.of(MyEntityBasedOnShardingBaseEntity);

interface AbstractRepositoryService<Entity> {
    create(entityLike: DeepPartial<Entity>): Entity | Entity[];
    create(entityLike: DeepPartial<Entity>): Entity | Entity[];
    create(entityLike?: DeepPartial<Entity> | DeepPartial<Entity>[]): Entity | Entity[];

    save(entities: DeepPartial<Entity>[], options?: SaveOptions): Promise<Entity[]>;
    save(entity: DeepPartial<Entity>, options?: SaveOptions): Promise<Entity>;

    remove(entities: Entity[], options?: RemoveOptions): Promise<Entity[]>;
    remove(entity: Entity, options?: RemoveOptions): Promise<Entity>;

    softRemove(entities: Entity[], options?: SaveOptions): Promise<Entity[]>;
    softRemove(entity: Entity, options?: SaveOptions): Promise<Entity>;

    update(
        criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptionsWhere<Entity>,
        partialEntity: QueryDeepPartialEntity<Entity>
    ): Promise<UpdateResult>;

    delete(
        criteria: string | string[] | number | number[] | Date | Date[] | ObjectID | ObjectID[] | FindOptionsWhere<Entity>
    ): Promise<DeleteResult>;

    count(options?: FindManyOptions<Entity>): Promise<number>;
    countBy(where: FindOptionsWhere<Entity>): Promise<number>;

    find(options?: FindManyOptions<Entity>): Promise<Entity[]>;
    findBy(where: FindOptionsWhere<Entity>): Promise<Entity[]>;

    findAndCount(options?: FindManyOptions<Entity>): Promise<[Entity[], number]>;
    findAndCountBy(where: FindOptionsWhere<Entity>): Promise<[Entity[], number]>;

    findOne(options: FindOneOptions<Entity>): Promise<Entity | null | undefined>;
    findOneBy(where: FindOptionsWhere<Entity>): Promise<Entity | null | undefined>;
    findOneById(id: string | number | Date | ObjectID): Promise<Entity | null>;
    findByIds(ids: any[]): Promise<Entity[]>;
}

4. Entity [static] method

// TypeORM.BaseEntity와 거의 동일한 기능들을 제공합니다.
const entity = await Case1.save({
    firstName: 'Typeorm',
    lastName: 'Sharding',
    age: 10,
});

await entity.save();
await entity.remove();
await entity.softRemove();
await entity.recover();
await entity.reload();


//      _______.___________.    ___   .___________. __    ______ 
//     /       |           |   /   \  |           ||  |  /      |
//    |   (----`---|  |----`  /  ^  \ `---|  |----`|  | |  ,----'
//     \   \       |  |      /  /_\  \    |  |     |  | |  |     
// .----)   |      |  |     /  _____  \   |  |     |  | |  `----.
// |_______/       |__|    /__/     \__\  |__|     |__|  \______|

// Entity instance를 생성합니다.
Case1.create();
Case1.create({firstName: 'Typeorm', ...});

// 모든 shard의 모든 entity를 반환합니다. 정렬 순서는 보장되지 않습니다.
await Case1.find();

// 모든 shard에서 firstName이 Typeorm인 모든 entity를 반환합니다. 정렬 순서는 보장되지 않습니다.
await Case1.find({ where: {firstName: 'Typeorm'} });

// 모든 shard를 검색해 firstName이 Typeorm인 하나의 entity를 반환합니다.
// 여러 shard에서 발견된 경우 가장 오래된 shard의 entity가 반환됩니다.
await Case1.findOneBy({ firstName: 'Typeorm' });

// ID로 검색하여 하나의 entity를 반환합니다.
await Case1.findOneById(1);

// 모든 shard에서 firstName이 Typeorm인 모든 entity의 수를 반환합니다.
await Case1.count({ where: {firstName: 'Typeorm'} });

// 여러 entity를 update합니다.
await Case1.update({ firstName: 'Typeorm' }, { lastName: 'Bob' });

// Entity를 삭제합니다.
await Case1.remove(entity);


//  __        ______   ____    __    ____     __       ___________    ____  _______  __      
// |  |      /  __  \  \   \  /  \  /   /    |  |     |   ____\   \  /   / |   ____||  |     
// |  |     |  |  |  |  \   \/    \/   /     |  |     |  |__   \   \/   /  |  |__   |  |     
// |  |     |  |  |  |   \            /      |  |     |   __|   \      /   |   __|  |  |     
// |  `----.|  `--'  |    \    /\    /       |  `----.|  |____   \    /    |  |____ |  `----.
// |_______| \______/      \__/  \__/        |_______||_______|   \__/     |_______||_______|

// 모든 TypeORM DataSource
Case1.getAllDataSource();

// 특정 entity를 담당하는 TypeORM DataSource
Case1.getDataSource(entity);

// 특정 ID를 담당하는 TypeORM DataSource
Case1.getDataSourceById(ID_VALUE);

// 모든 TypeORM Reposigory
Case1.getAllRepository<Case1>();

// 특정 entity를 담당하는 TypeORM Reposigory
Case1.getRepository<Case1>(entity);

// 특정 entity를 담당하는 TypeORM Manager
Case1.getManager<Case1>(entity);

Contributors