Skip to content

Commit

Permalink
feat: impl trigger Hooks (#289)
Browse files Browse the repository at this point in the history
Refs:
- #282
  • Loading branch information
killagu authored Aug 16, 2022
1 parent 79cb826 commit 41c6e24
Show file tree
Hide file tree
Showing 25 changed files with 856 additions and 68 deletions.
3 changes: 3 additions & 0 deletions app/common/LogUtil.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function isoNow() {
return new Date().toISOString();
}
14 changes: 14 additions & 0 deletions app/common/enum/Hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,17 @@ export enum HookType {
Scope = 'scope',
Owner = 'owner',
}

export enum HookEventType {
Star = 'package:star',
Unstar = 'package:unstar',
Publish = 'package:publish',
Unpublish = 'package:unpublish',
Owner = 'package:owner',
OwnerRm = 'package:owner-rm',
DistTag = 'package:dist-tag',
DistTagRm = 'package:dist-tag-rm',
Deprecated = 'package:deprecated',
Undeprecated = 'package:undeprecated',
Change = 'package:change',
}
2 changes: 2 additions & 0 deletions app/common/enum/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ export enum TaskType {
SyncPackage = 'sync_package',
ChangesStream = 'changes_stream',
SyncBinary = 'sync_binary',
CreateHook = 'create_hook',
TriggerHook = 'trigger_hook',
}

export enum TaskState {
Expand Down
14 changes: 14 additions & 0 deletions app/core/entity/Hook.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { Entity, EntityData } from './Entity';
import { EasyData, EntityUtil } from '../util/EntityUtil';
import { HookType } from '../../common/enum/Hook';
import crypto from 'crypto';

export type CreateHookData = Omit<EasyData<HookData, 'hookId'>, 'enable' | 'latestTaskId'>;

export interface HookData extends EntityData {
Expand Down Expand Up @@ -44,4 +46,16 @@ export class Hook extends Entity {
const newData = EntityUtil.defaultData(hookData, 'hookId');
return new Hook(newData);
}

// payload 可能会特别大,如果做多次 stringify 浪费太多 cpu
signPayload(payload: object): { digest, payloadStr } {
const payloadStr = JSON.stringify(payload);
const digest = crypto.createHmac('sha256', this.secret)
.update(JSON.stringify(payload))
.digest('hex');
return {
digest,
payloadStr,
};
}
}
93 changes: 93 additions & 0 deletions app/core/entity/HookEvent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { HookEventType } from '../../common/enum/Hook';

export interface PublishChangePayload {
'dist-tag'?: string;
version: string;
}

export interface UnpublishChangePayload {
'dist-tag'?: string;
version?: string;
}

export interface DistTagChangePayload {
'dist-tag': string;
}

export interface PackageOwnerPayload {
maintainer: string;
}

export interface DeprecatedChangePayload {
deprecated: string;
}

export class HookEvent<T = object> {
readonly changeId: string;
readonly event: HookEventType;
readonly fullname: string;
readonly type: 'package';
readonly version: '1.0.0';
readonly change: T;
readonly time: number;

constructor(event: HookEventType, changeId: string, fullname: string, change: T) {
this.changeId = changeId;
this.event = event;
this.fullname = fullname;
this.type = 'package';
this.version = '1.0.0';
this.change = change;
this.time = Date.now();
}

static createPublishEvent(fullname: string, changeId: string, version: string, distTag?: string): HookEvent<PublishChangePayload> {
return new HookEvent(HookEventType.Publish, changeId, fullname, {
'dist-tag': distTag,
version,
});
}

static createUnpublishEvent(fullname: string, changeId: string, version?: string, distTag?: string): HookEvent<UnpublishChangePayload> {
return new HookEvent(HookEventType.Unpublish, changeId, fullname, {
'dist-tag': distTag,
version,
});
}

static createOwnerEvent(fullname: string, changeId: string, maintainer: string): HookEvent<PackageOwnerPayload> {
return new HookEvent(HookEventType.Owner, changeId, fullname, {
maintainer,
});
}

static createOwnerRmEvent(fullname: string, changeId: string, maintainer: string): HookEvent<PackageOwnerPayload> {
return new HookEvent(HookEventType.OwnerRm, changeId, fullname, {
maintainer,
});
}

static createDistTagEvent(fullname: string, changeId: string, distTag: string): HookEvent<DistTagChangePayload> {
return new HookEvent(HookEventType.DistTag, changeId, fullname, {
'dist-tag': distTag,
});
}

static createDistTagRmEvent(fullname: string, changeId: string, distTag: string): HookEvent<DistTagChangePayload> {
return new HookEvent(HookEventType.DistTagRm, changeId, fullname, {
'dist-tag': distTag,
});
}

static createDeprecatedEvent(fullname: string, changeId: string, deprecated: string): HookEvent<DeprecatedChangePayload> {
return new HookEvent(HookEventType.Deprecated, changeId, fullname, {
deprecated,
});
}

static createUndeprecatedEvent(fullname: string, changeId: string, deprecated: string): HookEvent<DeprecatedChangePayload> {
return new HookEvent(HookEventType.Undeprecated, changeId, fullname, {
deprecated,
});
}
}
89 changes: 81 additions & 8 deletions app/core/entity/Task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,23 @@ import { Entity, EntityData } from './Entity';
import { EasyData, EntityUtil } from '../util/EntityUtil';
import { TaskType, TaskState } from '../../common/enum/Task';
import dayjs from '../../common/dayjs';
import { HookEvent } from './HookEvent';

const HOST_NAME = os.hostname();
const PID = process.pid;

export interface TaskData extends EntityData {
export interface TaskBaseData {
taskWorker: string;
}

export interface TaskData<T = TaskBaseData> extends EntityData {
taskId: string;
type: TaskType;
state: TaskState;
targetName: string;
authorId: string;
authorIp: string;
data: any;
data: T;
logPath?: string;
logStorePosition?: string;
attempts?: number;
Expand All @@ -33,21 +38,50 @@ export type SyncPackageTaskOptions = {
forceSyncHistory?: boolean;
};

export class Task extends Entity {
export interface CreateHookTaskData extends TaskBaseData {
hookEvent: HookEvent;
}

export interface TriggerHookTaskData extends TaskBaseData {
hookEvent: HookEvent;
hookId: string;
responseStatus?: number;
}

export interface CreateSyncPackageTaskData extends TaskBaseData {
tips?: string;
skipDependencies?: boolean;
syncDownloadData?: boolean;
forceSyncHistory?: boolean;
}

export interface ChangeStreamTaskData extends TaskBaseData {
since: string;
last_package?: string,
last_package_created?: Date,
task_count?: number,
}

export type CreateHookTask = Task<CreateHookTaskData>;
export type TriggerHookTask = Task<TriggerHookTaskData>;
export type CreateSyncPackageTask = Task<CreateSyncPackageTaskData>;
export type ChangeStreamTask = Task<ChangeStreamTaskData>;

export class Task<T extends TaskBaseData = TaskBaseData> extends Entity {
taskId: string;
type: TaskType;
state: TaskState;
targetName: string;
authorId: string;
authorIp: string;
data: any;
data: T;
logPath: string;
logStorePosition: string;
attempts: number;
error: string;
bizId?: string;

constructor(data: TaskData) {
constructor(data: TaskData<T>) {
super(data);
this.taskId = data.taskId;
this.type = data.type;
Expand All @@ -72,12 +106,12 @@ export class Task extends Entity {
this.data.taskWorker = `${HOST_NAME}:${PID}`;
}

private static create(data: EasyData<TaskData, 'taskId'>): Task {
private static create<T extends TaskBaseData>(data: EasyData<TaskData<T>, 'taskId'>): Task<T> {
const newData = EntityUtil.defaultData(data, 'taskId');
return new Task(newData);
}

public static createSyncPackage(fullname: string, options?: SyncPackageTaskOptions): Task {
public static createSyncPackage(fullname: string, options?: SyncPackageTaskOptions): CreateSyncPackageTask {
const data = {
type: TaskType.SyncPackage,
state: TaskState.Waiting,
Expand All @@ -98,7 +132,7 @@ export class Task extends Entity {
return task;
}

public static createChangesStream(targetName: string): Task {
public static createChangesStream(targetName: string): ChangeStreamTask {
const data = {
type: TaskType.ChangesStream,
state: TaskState.Waiting,
Expand All @@ -114,6 +148,45 @@ export class Task extends Entity {
return this.create(data);
}

public static createCreateHookTask(hookEvent: HookEvent): CreateHookTask {
const data = {
type: TaskType.CreateHook,
state: TaskState.Waiting,
targetName: hookEvent.fullname,
authorId: `pid_${process.pid}`,
authorIp: os.hostname(),
bizId: `CreateHook:${hookEvent.changeId}`,
data: {
// task execute worker
taskWorker: '',
hookEvent,
},
};
const task = this.create(data);
task.logPath = `/packages/${hookEvent.fullname}/hooks/${dayjs().format('YYYY/MM/DDHHmm')}-${task.taskId}.log`;
return task;
}

public static createTriggerHookTask(hookEvent: HookEvent, hookId: string): TriggerHookTask {
const data = {
type: TaskType.TriggerHook,
state: TaskState.Waiting,
targetName: hookEvent.fullname,
authorId: `pid_${process.pid}`,
bizId: `TriggerHook:${hookEvent.changeId}:${hookId}`,
authorIp: os.hostname(),
data: {
// task execute worker
taskWorker: '',
hookEvent,
hookId,
},
};
const task = this.create(data);
task.logPath = `/packages/${hookEvent.fullname}/hooks/${dayjs().format('YYYY/MM/DDHHmm')}-${task.taskId}.log`;
return task;
}

public static createSyncBinary(targetName: string, lastData: any): Task {
const data = {
type: TaskType.SyncBinary,
Expand Down
Loading

0 comments on commit 41c6e24

Please sign in to comment.