-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
17 changed files
with
485 additions
and
365 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { DataSourceId } from './DataSource'; | ||
import { ErrorObject } from 'ajv'; | ||
import { Patch } from 'rfc6902'; | ||
|
||
type TimestampNormal = { | ||
/** | ||
* 平台的时间戳,必须是毫秒级的,精度不足的应当补零 | ||
*/ | ||
timestamp: number; | ||
/** | ||
* 时间戳精度 | ||
*/ | ||
timestampPrecision: 'day' | 'hour' | 'minute' | 'second' | 'ms'; | ||
}; | ||
type TimestampNone = { | ||
/** | ||
* 没有时间戳 | ||
*/ | ||
timestampPrecision: 'none'; | ||
}; | ||
export type Timestamp = TimestampNormal | TimestampNone; | ||
|
||
export enum DataContentType { | ||
COMMON = 'common', | ||
JSON = 'json', | ||
KV = 'kv', | ||
} | ||
|
||
type DataContentCommon = { | ||
/** | ||
* 通用数据类型 | ||
*/ | ||
type: DataContentType.COMMON; | ||
/** | ||
* 数据id,通常使用平台提供的id即可,不同数据源的id值可以重复 | ||
*/ | ||
id: string; | ||
/** | ||
* 饼的原始内容 | ||
*/ | ||
rawContent: string; | ||
/** | ||
* 饼的额外内容 | ||
*/ | ||
extraRawContent?: Record<string, string>; | ||
}; | ||
/** | ||
* 用于监视json | ||
*/ | ||
export type DataContentJson<T = unknown> = { | ||
/** | ||
* json类型 | ||
*/ | ||
type: DataContentType.JSON; | ||
|
||
/** | ||
* 旧内容 | ||
*/ | ||
oldValue: T; | ||
/** | ||
* 新内容 | ||
*/ | ||
newValue: T; | ||
/** | ||
* 将oldValue转换成newValue的patch | ||
*/ | ||
patch: Patch; | ||
/** | ||
* patch中涉及到的全部路径,代表有哪些路径被修改了 | ||
*/ | ||
changePaths: string[]; | ||
}; | ||
|
||
export type PrimitiveWithEmpty = string | boolean | number | undefined | null; | ||
/** | ||
* 用于监视简单值的key/value, | ||
*/ | ||
export type DataContentKeyValue = { | ||
/** | ||
* key/value类型 | ||
*/ | ||
type: DataContentType.KV; | ||
|
||
/** | ||
* 旧KV键值对 | ||
*/ | ||
oldValue: Record<string, PrimitiveWithEmpty>; | ||
/** | ||
* 新KV键值对 | ||
*/ | ||
newValue: Record<string, PrimitiveWithEmpty>; | ||
|
||
/** | ||
* 所有更新的key | ||
*/ | ||
changeKeys: string[]; | ||
}; | ||
export type DataContentUnion = DataContentCommon | DataContentJson | DataContentKeyValue; | ||
/** | ||
* 一个饼 | ||
*/ | ||
export type DataItem = { | ||
/** | ||
* 数据源id | ||
*/ | ||
dataSourceId: DataSourceId; | ||
/** | ||
* 蹲饼器蹲到这个饼的时间(unix毫秒时间戳) | ||
*/ | ||
fetchTime: number; | ||
/** | ||
* 响应结构不满足预定义结构时产生的异常。 | ||
* 如果是通过正常蹲饼流程拿到的DataItem对象,该字段不会被json序列化输出 | ||
*/ | ||
schemaErrors?: ErrorObject[]; | ||
} & DataContentUnion & | ||
Timestamp; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,56 +1,60 @@ | ||
import { DataSource, DataSourceTypeInfo } from './DataSource'; | ||
import { createPatch } from 'rfc6902'; | ||
import { DataContentJson } from '../fetch/FetchResult'; | ||
import { Pointer } from 'rfc6902/pointer'; | ||
import { DataSourceConfig } from './DataSourceConfig'; | ||
|
||
const DEFAULT_KEY = 'default'; | ||
|
||
export abstract class JsonDataSource extends DataSource { | ||
private readonly jsonValues: Record<string, unknown> = {}; | ||
import { DataContentJson, DataContentType } from './DataContent'; | ||
|
||
/** | ||
* Json数据源 | ||
*/ | ||
// noinspection JSUnusedGlobalSymbols | ||
export abstract class JsonDataSource<T = unknown> extends DataSource { | ||
protected oldValue: T | undefined; | ||
/** | ||
* 暂时只在首次检查新值时初始化 | ||
*/ | ||
protected inited = false; | ||
|
||
/** | ||
* @see DataSource#constructor | ||
*/ | ||
protected constructor(type: DataSourceTypeInfo, dataId: string, config: DataSourceConfig) { | ||
protected constructor( | ||
type: DataSourceTypeInfo, | ||
dataId: string, | ||
config: DataSourceConfig, | ||
private readonly monitorPointers: Pointer[] | ||
) { | ||
super(type, dataId, config); | ||
} | ||
|
||
protected set(name: string, value: unknown): void; | ||
protected set(value: unknown): void; | ||
protected set(_key: unknown, _value?: unknown) { | ||
const { key, value } = this.extraKV(_key, _value); | ||
this.jsonValues[key] = value; | ||
} | ||
|
||
protected hasKey(name = DEFAULT_KEY) { | ||
return !!this.jsonValues[name]; | ||
} | ||
|
||
protected diff(name: string, value: unknown): void; | ||
protected diff(value: unknown): void; | ||
protected diff(_key: unknown, _value?: unknown) { | ||
const { key, value } = this.extraKV(_key, _value); | ||
const oldValue = this.jsonValues[key]; | ||
return createPatch(oldValue, value); | ||
} | ||
|
||
protected createContent<T = unknown>(oldValue: T, newValue: T): DataContentJson { | ||
const patch = createPatch(oldValue, newValue); | ||
const paths = patch.map((it) => it.path); | ||
return { | ||
type: 'json', | ||
oldValue: oldValue, | ||
newValue: newValue, | ||
patch: patch, | ||
changePaths: paths, | ||
}; | ||
} | ||
|
||
private extraKV(name: unknown, value?: unknown) { | ||
if (typeof value === 'undefined' || typeof name !== 'string') { | ||
return { key: DEFAULT_KEY, value: name }; | ||
} else { | ||
return { key: name, value: value }; | ||
protected createContentIfChanged(newValue: T): DataContentJson | undefined { | ||
if (!this.inited) { | ||
this.oldValue = newValue; | ||
this.inited = true; | ||
return; | ||
} | ||
try { | ||
const patch = createPatch(this.oldValue, newValue); | ||
if (patch.length === 0) return; | ||
let changed = false; | ||
for (const pointer of this.monitorPointers) { | ||
const subPatch = createPatch(pointer.get(this.oldValue), pointer.get(newValue)); | ||
if (subPatch.length > 0) { | ||
changed = true; | ||
break; | ||
} | ||
} | ||
if (!changed) return; | ||
const paths = patch.map((it) => it.path); | ||
return { | ||
type: DataContentType.JSON, | ||
oldValue: this.oldValue, | ||
newValue: newValue, | ||
patch: patch, | ||
changePaths: paths, | ||
}; | ||
} finally { | ||
this.oldValue = newValue; | ||
} | ||
} | ||
} |
Oops, something went wrong.