1.2.7 • Published 5 months ago

@xiaoguomeiyitian/core v1.2.7

Weekly downloads
-
License
-
Repository
-
Last release
5 months ago

框架概述

一个基于实体模型的前后端数据同步框架,支持热更新、自动同步和持久化存储,通过 RPC 调用实现分布式部署

特性

  • 🔄 热更新: 支持通过 loadfile 动态更新实体类
  • 🔗 双向调用: 支持前后端之间的实体方法互相调用
  • 📝 声明式配置: 通过注释标记实现属性的配置管理
  • 🚀 自动同步: 后端实体数据自动同步至前端
  • 💾 自动存储: 带有 @save 标记的属性自动保存至数据库
  • 🌐 分布式部署: 基于 RPC 调用的分布式架构
  • 📦 数据持久化: 支持 MongoDB 存储和 Redis 缓存
  • 💽 进程缓存: 使用 LevelDB 进程实体数据保存,支持进程崩溃后数据恢复
  • ⚖️ 弹性伸缩: 支持服务进程根据负载自动扩缩容
  • 🔍 在线调试: 支持实时调试和性能分析
    • HeapProfiler: 查看 V8 引擎内存快照
    • Profiler: 统计 CPU 调用信息
    • GCProfiler: 监控垃圾回收统计

cli

  • core dbg 在线调试
  • core defs 生成类型定义
  • core func 生成调用函数列表

实体定义示例

export interface Player {
    /** 唯一编号 @save */
    id?: string;
    /** @default 127.0.0.1 @server @save */
    ip?: string;
    /** 账号 @save */
    account?: string
    /** 服务器id @save */
    sid?: number;
    /** 创号时间 @save */
    cTime?: number;
    /** 昵称 @default nickname @save */
    nickname?: string;
    /** 公会id @default 0 @save */
    ghId?: string;
}

属性标记说明

  • @save: 标记需要持久化存储的属性
  • @server: 标记仅在服务器端存在的属性(不会同步到客户端)
  • @default value: 设置属性的默认值

示例

同步实体到前端

export class Player extends BaseEntity implements PlayerServer {
    /** 创建实体时调用 */
    async onCreate() {
        this.syncEntity();//同步实体到前端
    }
    /** 实体销毁时调用 */
    async onDestroy() {
  
    }
    /** 实体属性变化时调用 */
    async onPropChange(prop: string, value: any) {
  
    }
}

前端调用后端

export class Player extends Entity implements PlayerClient {
    server: PlayerServer;
    /** 修改头像 */
    modifyNickname(nickname: string) {
        //调用后端player实体  modifyNickname 修改实体昵称
        this.server.modifyNickname({ nickname: nickname });
    }
    /** 收到断线重连 */
    async onReConnection(msg: MsgonReConnection) {
        if (msg.roomtype == 0) return G.removeLoading();
        console.log("需要断线重连");
    }
    /** 当属性更新 */
    onPropChange(prop, oldVal, value) {
        console.log(prop, oldVal, value);
    }
}

后端调用前端

export class Player extends BaseEntity implements PlayerServer {
    client: PlayerClient;
    async onCreate() {
        //调用前端player实体的  onReConnection 函数通知前端是否断线重连
        this.client.onReConnection({ roomtype: 0, url: "" });
    }
    async onDestroy() {
  
    }
    /** 修改昵称 */
    modifyNickname(msg: MsgmodifyNickname, call?: MsgCall<MsgmodifyNickname, any>) { 
        this.nickname = msg.nickname; 
    }
}
  1. 后端收到前端调用 modifyNickname 函数,直接修改 this.nickname = msg.nickname 即可,
  2. 底层会把修改后的内容同步到前端和写入到数据库中。
  3. 底层会自动优化写入和同步逻辑,会在所有同步逻辑执行完毕异步逻辑发起之前进行同步和写入

RPC调用

//hall进程中的player类
export class Player extends BaseEntity implements PlayerServer {
    client: PlayerClient;
    async onCreate() {
        //rpc调用游戏服的RoomManage的getRoomtype获取玩家的房间id
        const res = (await G.getRpc("RoomManager", server.surl).getRoomtype({ uid: this.id })).res;
        //调用前端player实体的  onReConnection 函数通知前端是否断线重连
        this.client.onReConnection({ roomtype: res.roomType, url: "" });
    }
    async onDestroy() {
  
    }
}
//game进程的RoomManager类
export class RoomManager extends BaseEntity implements RoomManagerRpc {
    /**根据玩家id获取房间类型 */
    async getRoomtype(req: ReqgetRoomtype, call: DefaultCall<ReqgetRoomtype, ResgetRoomtype, any> = defaultCall): Promise<ApiReturn<ResgetRoomtype>> {
        const room = this.getRoomByPlayerId(req.uid);
        return call.succ({ roomType: room.roomType });
    }
}

热更新实体

G.loadfile("./server/hall/Player.js");

API

export declare class Global {
    /** cwd路径 */
    _cwdDir: string;
    event: EventEmitter;
    entityDefs: any;
    serviceProto: any;
    serviceProtoServer: any;
    constructor();
    init(entityDefs: any, serviceProto: any, serviceProtoServer: any): Promise<void>;
    /**获取某类实体属性的类型 */
    getPropType(type: string, prop: string): any;
    /**获取某类实体属性的默认值 */
    getPropDefault(type: string, prop: string): any;
    /**从redis读取数据 */
    loadByRedis(type: string, id: string): Promise<any>;
    /**数据写入到redis */
    setToRedis(type: string, id: string, data: any): Promise<void>;
    /**根据条件从mongo中查询单条实体数据*/
    findOne(type: string, filter: any, keys?: string[]): Promise<any>;
    /**根据条件从mongo中查询多条实体数据*/
    find(type: string, filter: any, keys?: string[]): Promise<any>;
    /**创建实体 单个进程只会创建一个相同id的实体*/
    create(type: string, id?: string, cdata?: any): Promise<any>;
    /**根据类型和id获取实体 */
    get(type: string, id?: string): any;
    /**获取rpc对象 */
    getRpc(type: string, serverUrl: string): any;
    /**获取某类实体属性的类型 */
    getByType(type: string): any[];
    /**加载某个文件夹下的所有文件 reChain 是否更新继承链上的其他实体 @param { boolean} reload 是否重新加载文件 默认:false */
    loadAllFile(source: string, reChain?: boolean, reload?: boolean): void;
    /**热更新某个文件 @param { boolean} reChain 是否更新继承链上的其他实体 @param { boolean} reload 是否重新加载文件 默认:true */
    loadfile(filePath: string, reChain?: boolean, reload?: boolean): Promise<void>;
    /**保存之前没有保存的dump数据*/
    flushDumpData(): Promise<void>;
    /** 获取V8 CPU调用统计信息,默认统计10秒钟 cwd/profile.cpuprofile*/
    profiler(time?: number): void;
    /** 获取V8 GC统计信息,默认统计10秒钟 */
    profilerGC(time?: number): void;
    /** 生成内存快照 cwd/heapSnapshot.heapsnapshot*/
    profilerHeap(password: string): void;
}
export declare class Entity {
    type: string; /** 实体类型 */
    id: string; /** 实体id */
    /** 连接列表 */
    conns: WsConnection[];
    constructor(type: string, id?: string);
    /**获取属性类型 */
    getPropType(prop: string): any;
    /**获取未定义的数据默认值 */
    getPropDefault(prop: string): any;
    /**递归地设置对象中的值 */
    setValueByPath(path: string[], value: any, type?: "inc" | "set" | "unset" | "push" | "pull", ext?: {
        min?: number;
        max?: number;
        leng?: number;
    }): void;
    /**递归地获取对象中的值 */
    getValueByPath(path: string[]): any;
    /**保持数据至缓存 */
    saveToDump(prop: string, value: any): Promise<void>;
    /**属性变化 */
    propChange(prop: string, value: any, key?: string): Promise<void>;
    /**创建 */
    create(): Promise<void>;
    /**实体同步到客户端 */
    syncEntity(conns?: WsConnection[]): void;
    /**写入数据库 */
    flush(): Promise<void>;
    /**销毁 */
    destroy(): Promise<void>;
    /**添加定时器 */
    addOneLoop(funcName: Function, time: number): number;
    /**清除定时器 */
    clearOneLoop(timeId: number): void;
    /**添加循环 */
    addLoop(funcName: Function, time: number): number;
    /**清除循环 */
    clearLoop(timeId: number): void;
    /**清除所有定时器 */
    clearAllLoop(): void;
    onCreate(): void;
    onPropChange(prop: string, value: any): void;
    onDestroy(): void;
}
export declare class GenEntityDefs {
    gen(filePath: string): void;
}
export declare class GenServiceFunc {
    gen(fReadPath: string, fWritePath: string, types: string[]): void;
}
1.2.7

5 months ago

1.2.6

5 months ago

1.2.5

5 months ago

1.2.4

5 months ago

1.2.3

6 months ago

1.2.2

6 months ago

1.2.1

6 months ago

1.2.0

6 months ago

1.1.9

6 months ago

1.1.1

7 months ago

1.1.8

6 months ago

1.1.7

6 months ago

1.1.6

6 months ago

1.1.5

7 months ago

1.1.4

7 months ago

1.1.3

7 months ago

1.1.2

7 months ago

1.1.0

7 months ago

1.0.9

7 months ago

1.0.8

7 months ago

1.0.7

7 months ago

1.0.6

7 months ago

1.0.5

7 months ago

1.0.4

7 months ago

1.0.3

7 months ago

1.0.1

7 months ago

1.0.0

7 months ago