Skip to content

Commit

Permalink
refactor(services): replace current collection service API
Browse files Browse the repository at this point in the history
  • Loading branch information
oceanlvr committed Aug 12, 2021
1 parent cfa878d commit 313a4c7
Show file tree
Hide file tree
Showing 18 changed files with 175 additions and 187 deletions.
11 changes: 6 additions & 5 deletions .github/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,18 +130,19 @@ yarn run db:migration:[run|revert]

If your table models is not stable, and there are development mode without any data. you could just use:

1. `yarn run db:log` check CLI sync execute SQL queries
2. `db:migration:sync` sync models to database
3. `yarn run db:diagram` (optional) get a latest ER diagram
1. `yarn run db:migration:drop` (optional) drop all DDL schema includes its entities
2. `yarn run db:log` (optional) check CLI sync execute SQL queries
3. `db:migration:sync` sync models to database
4. `yarn run db:diagram` (optional) get a latest ER diagram

Otherwise, Please follow bellow steps and know clearly what you do. Or there is a high risk to lost data.

1. `yarn run db:log` check CLI sync execute SQL queries
1. `yarn run db:log` (optional) check CLI sync execute SQL queries
2. `db:migration:generate -n {migration_name}` Automatic migration generate
3. `db:migration:run` make pending migrations executed. NOTICE: you should execute this code before the APP open since the table model changed.
4. `db:diagram` (optional) get a latest ER diagram.

Please use `db:migration:revert` to revert changes, and executing `db:migration:run`, `db:migration:sync` carefully.
Please use `db:migration:revert` to revert changes, and executing `db:migration:drop`, `db:migration:sync` carefully.

Reference:

Expand Down
11 changes: 6 additions & 5 deletions .github/CONTRIBUTING_CN.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,18 +128,19 @@ yarn run db:migration:[run|revert]

如果你正处于开发模式,并且在数据库中没有实际的数据,那么你可以放心地按照以下步骤同步

1. `yarn run db:log` 用于确定当前迁移将会执行的 SQL 语句
2. `db:migration:sync` 同步数据模型到数据库
3. `yarn run db:diagram` (可选的) 生成一个最新的 ER 关系图
1. `yarn run db:migration:drop` (可选的) 删除所有表格
2. `yarn run db:log` (可选的) 用于确定当前迁移将会执行的 SQL 语句
3. `db:migration:sync` 同步数据模型到数据库
4. `yarn run db:diagram` (可选的) 生成一个最新的 ER 关系图

否则,你应该遵循以下步骤,并且知道你正在做的每一步在干什么,否则将会有失去数据库的风险。

1. `yarn run db:log` 用于确定当前迁移将会执行的 SQL 语句
1. `yarn run db:log` (可选的) 用于确定当前迁移将会执行的 SQL 语句
2. `db:migration:generate -n {migration_name}` 自动生成迁移脚本
3. `db:migration:run` 运行迁移脚本。在版本更新时应该本地运行该迁移脚本
4. `db:diagram` (可选的) 生成一个最新的 ER 关系图

请使用 `db:migration:revert` 命令撤回上一次迁移, 执行 `db:migration:run`, `db:migration:sync` 命令时请当心.
请使用 `db:migration:revert` 命令撤回上一次迁移, 执行 `db:migration:drop`, `db:migration:sync` 命令时请当心.

参考:

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"db:migration:run": "TS_NODE_PROJECT=tsconfig.commonjs.json ts-node ./node_modules/.bin/typeorm migration:run -f ormconfig.ts",
"db:migration:revert": "TS_NODE_PROJECT=tsconfig.commonjs.json ts-node ./node_modules/.bin/typeorm migration:revert -f ormconfig.ts",
"db:migration:sync": "TS_NODE_PROJECT=tsconfig.commonjs.json ts-node ./node_modules/.bin/typeorm schema:sync -f ormconfig.ts",
"db:migration:clean":"TS_NODE_PROJECT=tsconfig.commonjs.json ts-node ./node_modules/.bin/typeorm schema:drop -f ormconfig.ts",
"db:diagram": "TS_NODE_PROJECT=tsconfig.commonjs.json ts-node ./node_modules/.bin/typeorm-uml ormconfig.ts -d ./src/database/database.png"
},
"main": "background.js",
Expand Down
8 changes: 0 additions & 8 deletions src/api/connection.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
import db from '@/database/index'

export const setConnectionCollection = (data: CollectionModel[] | []): CollectionModel[] | [] => {
return db.set<CollectionModel[] | []>('connectionsCollection', data)
}

export const loadConnectionsWithCollection = (): CollectionModel[] | [] => {
return db.get<CollectionModel[] | []>('connectionsCollection')
}

export const updateConnectionCollectionId = (id: string, collectionId: string | null): ConnectionModel => {
const connection: ConnectionModel = loadConnection(id)
if (connection) {
Expand Down
2 changes: 1 addition & 1 deletion src/database/database.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const ORMConfig = {
database: join(STORE_PATH, 'MQTTX.db'),
cache: true,
timezone: 'Z',
migrations: [initTable1627697951611],
migrations: [],
migrationsTableName: 'temp_migration_table',
entities: [
ConnectionEntity,
Expand Down
2 changes: 1 addition & 1 deletion src/database/models/CollectionEntity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export default class CollectionEntity {

// collections children
@TreeChildren()
collections!: CollectionEntity[]
children!: CollectionEntity[]

// connections children
@OneToMany(() => ConnectionEntity, (connection) => connection.parent)
Expand Down
15 changes: 10 additions & 5 deletions src/database/models/ConnectionEntity.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
// see https://typeorm.io/#/entities/column-types-for-sqlite--cordova--react-native--expo
import { Entity, Column, PrimaryGeneratedColumn, OneToMany, ManyToOne, OneToOne, JoinColumn } from 'typeorm'
import { Entity, Column, PrimaryGeneratedColumn, OneToMany, ManyToOne, OneToOne, JoinColumn, Index } from 'typeorm'
import MessageEntity from './MessageEntity'
import SubscriptionEntity from './SubscriptionEntity'
import CollectionEntity from './CollectionEntity'
import WillEntity from './WillEntity'

type Protocol = 'ws' | 'wss' | 'mqtt' | 'mqtts'
type CertType = '' | 'server' | 'self'

@Entity('ConnectionEntity')
export default class ConnectionEntity {
@PrimaryGeneratedColumn('uuid')
id?: string

@Column({ type: 'varchar' })
@Index({ unique: true })
@Column({ type: 'varchar', name: 'client_id' })
clientId!: string

@Column({ type: 'varchar' })
Expand Down Expand Up @@ -65,7 +70,7 @@ export default class ConnectionEntity {
@JoinColumn({ name: 'parent_id', referencedColumnName: 'id' })
parent?: CollectionEntity

@Column({ name: 'parent_id', nullable: true })
@Column({ name: 'parent_id', nullable: true, default: '' })
parentId?: string
// ManyToOne entities ends

Expand All @@ -87,8 +92,8 @@ export default class ConnectionEntity {
@Column({ type: 'boolean', default: false })
isCollection!: false

@OneToOne(() => WillEntity, (will) => will.connection, { cascade: true, onDelete: 'CASCADE' })
@JoinColumn({ name: 'id', referencedColumnName: 'id' })
@OneToOne(() => WillEntity, (will) => will.connection, { onDelete: 'CASCADE' })
@JoinColumn()
will?: WillEntity

@OneToMany(() => MessageEntity, (message) => message.connection)
Expand Down
2 changes: 2 additions & 0 deletions src/database/models/HistoryMessageHeaderEntity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'

type QoS = 0 | 1 | 2

@Entity('historyMessageHeaderEntity')
export default class HistoryMessageHeaderEntity {
@PrimaryGeneratedColumn('uuid')
Expand Down
2 changes: 2 additions & 0 deletions src/database/models/HistoryMessagePayloadEntity.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm'

type PayloadType = 'Plaintext' | 'Base64' | 'JSON' | 'Hex'

@Entity('historyMessagePayloadEntity')
export default class HistoryMessagePayloadEntity {
@PrimaryGeneratedColumn('uuid')
Expand Down
2 changes: 2 additions & 0 deletions src/database/models/MessageEntity.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Entity, Column, PrimaryGeneratedColumn, ManyToOne, JoinColumn } from 'typeorm'
import ConnectionEntity from './ConnectionEntity'

type QoS = 0 | 1 | 2

@Entity('MessageEntity')
export default class MessageEntity {
@PrimaryGeneratedColumn('uuid')
Expand Down
2 changes: 2 additions & 0 deletions src/database/models/SubscriptionEntity.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne, JoinColumn } from 'typeorm'
import ConnectionEntity from './ConnectionEntity'

type QoS = 0 | 1 | 2

@Entity('SubscriptionEntity')
export default class SubscriptionEntity {
@PrimaryGeneratedColumn('uuid')
Expand Down
2 changes: 2 additions & 0 deletions src/database/models/WillEntity.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Entity, PrimaryGeneratedColumn, Column, OneToOne } from 'typeorm'
import ConnectionEntity from './ConnectionEntity'

type QoS = 0 | 1 | 2

@Entity('WillEntity')
export default class WillEntity {
@PrimaryGeneratedColumn('uuid')
Expand Down
156 changes: 95 additions & 61 deletions src/database/services/CollectionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { InjectRepository } from 'typeorm-typedi-extensions'
import { Repository } from 'typeorm'
import CollectionEntity from '../models/CollectionEntity'
import ConnectionEntity from '../models/ConnectionEntity'
import WillEntity from '../models/WillEntity'

@Service()
export default class ConnectionService {
Expand All @@ -11,98 +12,131 @@ export default class ConnectionService {
private collectionRepository: Repository<CollectionEntity>,
@InjectRepository(ConnectionEntity)
private connectionRepository: Repository<ConnectionEntity>,
@InjectRepository(WillEntity)
private willRepository: Repository<WillEntity>,
) {}

// travel current layer of tree, composition collection and connection to children
private travelEntity(data: CollectionEntity[], connection: ConnectionEntity[]): ConnectionModelTree[] {
private async travelEntity(data: CollectionEntity[], parentId?: string): Promise<ConnectionModelTree[]> {
let res: ConnectionModelTree[] = []
data.map((collection) => {
let child: ConnectionModelTree[] = []
if (collection && collection.collections && collection.collections.length) {
child = this.travelEntity(collection.collections, collection.connections)
let connections: ConnectionModel[] = []
if (parentId) {
// find current collection's connections
const query: ConnectionEntity[] = await this.connectionRepository.find({
parentId,
})
if (query && query.length) {
connections = query as ConnectionModel[]
}
let children: ConnectionModelTree[] = child as ConnectionModelTree[]
if (connection) {
children = [...children, ...connection]
}
res.push({
id: collection.id,
name: collection.name,
children,
isCollection: true,
isEdit: false,
orderId: collection.orderId,
} as ConnectionModelTree)
})
return res
}
await Promise.all(
data.map(async (collection) => {
let children: ConnectionModelTree[] = []
if (collection) {
const curChildrens = collection.children ? collection.children : []
children = await this.travelEntity(curChildrens, collection.id)
}
res.push({
id: collection.id,
name: collection.name,
children,
isCollection: true,
isEdit: false,
orderId: collection.orderId,
} as ConnectionModelTree)
}),
)
return [...res, ...connections] as ConnectionModelTree[]
}

// travel current layer of tree, deconstruct children to collection and connection
private travelModel(
private async travelModel(
children: ConnectionModelTree[],
parentId?: string | undefined,
): {
collection: CollectionEntity[]
connection: ConnectionEntity[]
} {
): Promise<{ collection: CollectionEntity[]; connection: ConnectionEntity[] }> {
let collection: CollectionEntity[] = []
let connection: ConnectionEntity[] = []
children.forEach(async (treeNode: ConnectionModelTree) => {
if (treeNode.isCollection) {
const { collection: topCollection, connection: topConnection } = this.travelModel(
treeNode.children,
treeNode.id,
)
collection.push({
...treeNode,
collections: topCollection,
connections: topConnection,
})
} else if (!treeNode.isCollection) {
const parent: CollectionEntity | undefined = await this.collectionRepository.findOne(parentId)
if (parent) {
connection.push({
await Promise.all(
children.map(async (treeNode: ConnectionModelTree) => {
if (treeNode.isCollection) {
const { collection: topCollection, connection: topConnection } = await this.travelModel(
treeNode.children ? treeNode.children : [],
treeNode.id,
)
collection.push({
...treeNode,
parent,
})
} else {
connection.push(treeNode)
children: topCollection,
connections: topConnection,
} as CollectionEntity)
} else if (!treeNode.isCollection) {
if (parentId) {
const parent: CollectionEntity | undefined = await this.collectionRepository.findOne(parentId)
if (parent) {
connection.push({
...treeNode,
parent,
} as ConnectionEntity)
}
} else {
connection.push(treeNode as ConnectionEntity)
}
}
}),
)
if (collection.length) {
await this.collectionRepository.save(collection)
}
for (let i = 0; i < connection.length; i++) {
const query = await this.connectionRepository.findOne({
clientId: connection[i].clientId,
})
if (query) {
const updatedConnection: ConnectionEntity = { ...connection[i], id: query.id } as ConnectionEntity
await this.willRepository.save(updatedConnection.will as WillEntity)
await this.connectionRepository.save(updatedConnection)
} else {
await this.willRepository.save(connection[i].will as WillEntity)
await this.connectionRepository.insert(connection[i])
}
})
}
return { collection, connection }
}

public async setAll(data: ConnectionModelTree[] | undefined): Promise<ConnectionModelTree[] | undefined> {
if (data && data.length) {
const { collection, connection } = this.travelModel(data)
await this.collectionRepository.save(collection)
await this.connectionRepository.save(connection)
if (!data || !data.length) {
return
}
return data
const { collection, connection } = await this.travelModel(data)
if (collection && connection) {
// maybe not this condition
return data
}
return
}

public async getAll(): Promise<ConnectionModelTree[] | undefined> {
// TODO: maybe not undefine
const topConnections: ConnectionEntity[] = await this.connectionRepository.find({
parent: undefined,
parentId: '',
})
const query: CollectionEntity[] = await this.collectionRepository.manager
.getTreeRepository(CollectionEntity)
.findTrees()
if (!query) {
return
}
const collectionTree: ConnectionModelTree[] | undefined = query.map((treeNode) => {
return {
id: treeNode.id,
children: this.travelEntity(treeNode.collections, treeNode.connections),
name: treeNode.name,
isCollection: true,
isEdit: false,
orderId: treeNode.orderId,
}
})
const collectionTree: ConnectionModelTree[] | undefined = await Promise.all(
query.map(async (treeNode) => {
const children = await this.travelEntity(treeNode.children, treeNode.id)
return {
id: treeNode.id,
children,
name: treeNode.name,
isCollection: true,
isEdit: false,
orderId: treeNode.orderId,
} as CollectionModel
}),
)
return [...collectionTree, ...topConnections] as ConnectionModelTree[]
}
}
Loading

0 comments on commit 313a4c7

Please sign in to comment.