Skip to content

Commit deace16

Browse files
committed
♻️ 新储存引擎数据迁移
1 parent fcb4cc4 commit deace16

12 files changed

Lines changed: 260 additions & 53 deletions

File tree

src/app/migrate.ts

Lines changed: 201 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1+
import { getStorageName } from "@App/pkg/utils/utils";
12
import { db } from "./repo/dao";
2-
import { Script } from "./repo/scripts";
3+
import { Script, ScriptAndCode, ScriptCodeDAO, ScriptDAO } from "./repo/scripts";
4+
import { Subscribe, SubscribeDAO } from "./repo/subscribe";
5+
import { Value, ValueDAO } from "./repo/value";
6+
import { Permission, PermissionDAO } from "./repo/permission";
37

48
// 0.10.0重构,重命名字段,统一使用小峰驼
5-
function renameField(): void {
9+
function renameField() {
610
db.version(16)
711
.stores({
812
scripts:
@@ -32,10 +36,199 @@ function renameField(): void {
3236
// export是0.10.x时的兼容性处理
3337
export: "++id,&scriptId",
3438
});
39+
const v = 36;
3540
// 将脚本数据迁移到chrome.storage
36-
// db.version(18)
37-
// .stores({})
38-
// .upgrade((tx) => {});
41+
db.version(v).upgrade(() => {
42+
// 默认使用的事务,这里加个延时,用db.open()打开数据库后,再执行
43+
setTimeout(async () => {
44+
try {
45+
// 迁移脚本
46+
const scripts = await db.table("scripts").toArray();
47+
const scriptDAO = new ScriptDAO();
48+
const scriptCodeDAO = new ScriptCodeDAO();
49+
console.log("开始迁移脚本数据", scripts.length);
50+
await Promise.all(
51+
scripts.map(async (script: ScriptAndCode) => {
52+
const {
53+
uuid,
54+
name,
55+
namespace,
56+
author,
57+
originDomain,
58+
subscribeUrl,
59+
type,
60+
sort,
61+
status,
62+
runStatus,
63+
metadata,
64+
createtime,
65+
checktime,
66+
code,
67+
checkUpdateUrl,
68+
downloadUrl,
69+
selfMetadata,
70+
config,
71+
error,
72+
updatetime,
73+
lastruntime,
74+
nextruntime,
75+
} = script;
76+
const s = await scriptDAO.save({
77+
uuid,
78+
name,
79+
namespace,
80+
author,
81+
originDomain,
82+
origin,
83+
checkUpdateUrl,
84+
downloadUrl,
85+
metadata,
86+
selfMetadata,
87+
subscribeUrl,
88+
config,
89+
type,
90+
status,
91+
sort,
92+
runStatus,
93+
error,
94+
createtime,
95+
updatetime,
96+
checktime,
97+
lastruntime,
98+
nextruntime,
99+
});
100+
return scriptCodeDAO
101+
.save({
102+
uuid: s.uuid,
103+
code,
104+
})
105+
.catch((e) => {
106+
console.log("脚本代码迁移失败", e);
107+
return Promise.reject(e);
108+
});
109+
})
110+
);
111+
// 迁移订阅
112+
const subscribe = await db.table("subscribe").toArray();
113+
const subscribeDAO = new SubscribeDAO();
114+
if (subscribe.length) {
115+
await Promise.all(
116+
subscribe.map((s: Subscribe) => {
117+
console.log("1234", s);
118+
const { url, name, code, author, scripts, metadata, status, createtime, updatetime, checktime } = s;
119+
return subscribeDAO.save({
120+
url,
121+
name,
122+
code,
123+
author,
124+
scripts,
125+
metadata,
126+
status,
127+
createtime,
128+
updatetime,
129+
checktime,
130+
});
131+
})
132+
);
133+
}
134+
console.log("订阅数据迁移完成", subscribe.length);
135+
// 迁移value
136+
interface MV2Value {
137+
id: number;
138+
scriptId: number;
139+
storageName?: string;
140+
key: string;
141+
value: any;
142+
createtime: number;
143+
updatetime: number;
144+
}
145+
const values = await db.table("value").toArray();
146+
const valueDAO = new ValueDAO();
147+
const valueMap = new Map<string, Value>();
148+
await Promise.all(
149+
values.map((v: MV2Value) => {
150+
const { scriptId, storageName, key, value, createtime } = v;
151+
return db
152+
.table("scripts")
153+
.where("id")
154+
.equals(scriptId)
155+
.first((script: Script) => {
156+
if (script) {
157+
let data: { [key: string]: any } = {};
158+
if (!valueMap.has(script.uuid)) {
159+
valueMap.set(script.uuid, {
160+
uuid: script.uuid,
161+
storageName: getStorageName(script),
162+
data: data,
163+
createtime,
164+
updatetime: 0,
165+
});
166+
} else {
167+
data = valueMap.get(script.uuid)!.data;
168+
}
169+
data[key] = value;
170+
}
171+
});
172+
})
173+
);
174+
// 保存到数据库
175+
await Promise.all(
176+
Array.from(valueMap.keys()).map((uuid) => {
177+
const { storageName, data, createtime } = valueMap.get(uuid)!;
178+
return valueDAO.save(storageName!, {
179+
uuid,
180+
storageName,
181+
data,
182+
createtime,
183+
updatetime: 0,
184+
});
185+
})
186+
);
187+
console.log("脚本value数据迁移完成", values.length);
188+
// 迁移permission
189+
const permissions = await db.table("permission").toArray();
190+
const permissionDAO = new PermissionDAO();
191+
await Promise.all(
192+
permissions.map((p: Permission & { scriptId: number }) => {
193+
const { scriptId, permission, permissionValue, createtime, updatetime, allow } = p;
194+
return db
195+
.table("scripts")
196+
.where("id")
197+
.equals(scriptId)
198+
.first((script: Script) => {
199+
if (script) {
200+
return permissionDAO.save({
201+
uuid: script.uuid,
202+
permission,
203+
permissionValue,
204+
createtime,
205+
updatetime,
206+
allow,
207+
});
208+
}
209+
});
210+
})
211+
);
212+
console.log("脚本permission数据迁移完成", permissions.length);
213+
// 打开页面,告知数据储存+升级至了mv3,重启一次扩展
214+
setTimeout(async () => {
215+
const scripts = await scriptDAO.all();
216+
console.log("脚本数据迁移完成", scripts.length);
217+
if (scripts.length > 0) {
218+
chrome.tabs.create({
219+
url: "https://docs.scriptcat.org/docs/change/v0.17/",
220+
});
221+
setTimeout(() => {
222+
chrome.runtime.reload();
223+
}, 1000);
224+
}
225+
}, 2000);
226+
} catch (e) {
227+
console.error("脚本数据迁移失败", e);
228+
}
229+
}, 200);
230+
});
231+
return db.open();
39232
}
40233

41234
export default function migrate() {
@@ -90,7 +283,8 @@ export default function migrate() {
90283
value: "++id,scriptId,storageName,key,createtime",
91284
})
92285
.upgrade((tx) => {
93-
tx.table("value")
286+
return tx
287+
.table("value")
94288
.toCollection()
95289
.modify((value) => {
96290
if (value.namespace) {
@@ -112,5 +306,5 @@ export default function migrate() {
112306
permission: "++id,scriptId,[scriptId+permission+permissionValue],createtime,updatetime",
113307
});
114308
// 使用小峰驼统一命名规范
115-
renameField();
309+
return renameField();
116310
}

src/app/service/offscreen/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ export class OffscreenManager {
2020

2121
private serviceWorker = new ServiceWorkerClient(this.extensionMessage);
2222

23+
constructor(private extensionMessage:MessageSend) {
24+
25+
}
26+
2327
logger(data: Logger) {
2428
const dao = new LoggerDAO();
2529
dao.save(data);

src/app/service/service_worker/index.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,15 @@ export default class ServiceWorkerManager {
3535
const value = new ValueService(this.api.group("value"), this.sender);
3636
const script = new ScriptService(systemConfig, this.api.group("script"), this.mq, value, resource);
3737
script.init();
38-
const runtime = new RuntimeService(systemConfig, this.api.group("runtime"), this.sender, this.mq, value, script);
38+
const runtime = new RuntimeService(
39+
systemConfig,
40+
this.api.group("runtime"),
41+
this.sender,
42+
this.mq,
43+
value,
44+
script,
45+
resource
46+
);
3947
runtime.init();
4048
const popup = new PopupService(this.api.group("popup"), this.mq, runtime);
4149
popup.init();

src/app/service/service_worker/resource.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,22 @@ export class ResourceService {
3636
return Promise.resolve(undefined);
3737
}
3838

39+
cache: Map<string, { [key: string]: Resource }> = new Map();
40+
3941
public async getScriptResources(script: Script): Promise<{ [key: string]: Resource }> {
40-
return Promise.resolve({
42+
// 优先从内存中获取
43+
if (this.cache.has(script.uuid)) {
44+
return Promise.resolve(this.cache.get(script.uuid) || {});
45+
}
46+
// 资源不存在,重新加载
47+
const res = await Promise.resolve({
4148
...((await this.getResourceByType(script, "require")) || {}),
4249
...((await this.getResourceByType(script, "require-css")) || {}),
4350
...((await this.getResourceByType(script, "resource")) || {}),
4451
});
52+
// 缓存到内存
53+
this.cache.set(script.uuid, res);
54+
return res;
4555
}
4656

4757
async getResourceByType(script: Script, type: ResourceType): Promise<{ [key: string]: Resource }> {
@@ -159,6 +169,8 @@ export class ResourceService {
159169
}
160170

161171
public async addResource(url: string, uuid: string, type: ResourceType): Promise<Resource> {
172+
// 删除缓存
173+
this.cache.delete(uuid);
162174
const u = this.parseUrl(url);
163175
let result = await this.getResourceModel(u.url);
164176
// 资源不存在,重新加载

src/app/service/service_worker/runtime.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@ import Logger from "@App/app/logger/logger";
2626
import LoggerCore from "@App/app/logger/core";
2727
import PermissionVerify from "./permission_verify";
2828
import { SystemConfig } from "@App/pkg/config/config";
29+
import { ResourceService } from "./resource";
2930

30-
// 为了优化性能,存储到缓存时删除了code与value
31+
// 为了优化性能,存储到缓存时删除了code、value与resource
3132
export interface ScriptMatchInfo extends ScriptRunResouce {
3233
matches: string[];
3334
excludeMatches: string[];
@@ -54,7 +55,8 @@ export class RuntimeService {
5455
private sender: MessageSend,
5556
private mq: MessageQueue,
5657
private value: ValueService,
57-
private script: ScriptService
58+
private script: ScriptService,
59+
private resource: ResourceService
5860
) {}
5961

6062
async init() {
@@ -212,18 +214,18 @@ export class RuntimeService {
212214
return scriptRes;
213215
});
214216

215-
const enableScript = scripts.filter((item) => item);
217+
const enableScript = scripts.filter((item) => item) as ScriptMatchInfo[];
216218

217219
await Promise.all([
218220
// 加载value
219221
...enableScript.map(async (script) => {
220222
const value = await this.value.getScriptValue(script!);
221-
script!.value = value;
223+
script.value = value;
222224
}),
223225
// 加载resource
224226
...enableScript.map(async (script) => {
225-
// const resource = await this.script.buildScriptRunResource(script!);
226-
// script!.resource = resource;
227+
const resource = await this.resource.getScriptResources(script);
228+
script.resource = resource;
227229
}),
228230
]);
229231

@@ -328,8 +330,10 @@ export class RuntimeService {
328330
this.scriptMatchCache.forEach((val, key) => {
329331
scriptMatch[key] = val;
330332
// 优化性能,将不需要的信息去掉
333+
// 而且可能会超过缓存的存储限制
331334
scriptMatch[key].code = "";
332335
scriptMatch[key].value = {};
336+
scriptMatch[key].resource = {};
333337
});
334338
return await Cache.getInstance().set("scriptMatch", scriptMatch);
335339
}

src/offscreen.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,19 @@
1-
import migrate from "./app/migrate";
1+
import { MessageSend } from "@Packages/message/server";
22
import LoggerCore from "./app/logger/core";
3-
import DBWriter from "./app/logger/db_writer";
4-
import { LoggerDAO } from "./app/repo/logger";
3+
import MessageWriter from "./app/logger/message_writer";
54
import { OffscreenManager } from "./app/service/offscreen";
6-
7-
// 初始化数据库
8-
migrate();
5+
import { ExtensionMessageSend } from "@Packages/message/extension_message";
96

107
function main() {
118
// 初始化日志组件
9+
const extensionMessage: MessageSend = new ExtensionMessageSend();
1210
const loggerCore = new LoggerCore({
13-
writer: new DBWriter(new LoggerDAO()),
11+
writer: new MessageWriter(extensionMessage),
1412
labels: { env: "offscreen" },
1513
});
1614
loggerCore.logger().debug("offscreen start");
1715
// 初始化管理器
18-
const manager = new OffscreenManager();
16+
const manager = new OffscreenManager(extensionMessage);
1917
manager.initManager();
2018
}
2119

src/pages/confirm/main.tsx

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,12 @@ import "@App/index.css";
88
import { Provider } from "react-redux";
99
import { store } from "@App/pages/store/store.ts";
1010
import LoggerCore from "@App/app/logger/core.ts";
11-
import migrate from "@App/app/migrate.ts";
12-
import { LoggerDAO } from "@App/app/repo/logger.ts";
13-
import DBWriter from "@App/app/logger/db_writer.ts";
11+
import MessageWriter from "@App/app/logger/message_writer.ts";
12+
import { message } from "../store/global.ts";
1413

15-
// 初始化数据库
16-
migrate();
1714
// 初始化日志组件
1815
const loggerCore = new LoggerCore({
19-
writer: new DBWriter(new LoggerDAO()),
16+
writer: new MessageWriter(message),
2017
labels: { env: "confirm" },
2118
});
2219

0 commit comments

Comments
 (0)