fix: onchange bug
This commit is contained in:
parent
b510c7419f
commit
6dd1d4d83a
@ -1,102 +1,121 @@
|
|||||||
import {basename, dirname, join as pathjoin} from 'path';
|
import { basename, dirname, join as pathjoin } from 'path';
|
||||||
import {Document, DocumentAccessor} from '../model/mod';
|
import { Document, DocumentAccessor } from '../model/mod';
|
||||||
import { ContentFile, createContentFile } from '../content/mod';
|
import { ContentFile, createContentFile } from '../content/mod';
|
||||||
import {IDiffWatcher} from './watcher';
|
import { IDiffWatcher } from './watcher';
|
||||||
import {ContentList} from './content_list';
|
import { ContentList } from './content_list';
|
||||||
|
|
||||||
//refactoring needed.
|
//refactoring needed.
|
||||||
export class ContentDiffHandler{
|
export class ContentDiffHandler {
|
||||||
/** content file list waiting to add */
|
/** content file list waiting to add */
|
||||||
waiting_list:ContentList;
|
waiting_list: ContentList;
|
||||||
/** deleted contents */
|
/** deleted contents */
|
||||||
tombstone: Map<string,Document>;//hash, contentfile
|
tombstone: Map<string, Document>;//hash, contentfile
|
||||||
doc_cntr: DocumentAccessor;
|
doc_cntr: DocumentAccessor;
|
||||||
/** content type of handle */
|
/** content type of handle */
|
||||||
content_type: string;
|
content_type: string;
|
||||||
constructor(cntr: DocumentAccessor,content_type:string){
|
constructor(cntr: DocumentAccessor, content_type: string) {
|
||||||
this.waiting_list = new ContentList();
|
this.waiting_list = new ContentList();
|
||||||
this.tombstone = new Map<string,Document>();
|
this.tombstone = new Map<string, Document>();
|
||||||
this.doc_cntr = cntr;
|
this.doc_cntr = cntr;
|
||||||
this.content_type = content_type;
|
this.content_type = content_type;
|
||||||
}
|
}
|
||||||
async setup(){
|
async setup() {
|
||||||
const deleted = await this.doc_cntr.findDeleted(this.content_type);
|
const deleted = await this.doc_cntr.findDeleted(this.content_type);
|
||||||
for (const it of deleted) {
|
for (const it of deleted) {
|
||||||
this.tombstone.set(it.content_hash,it);
|
this.tombstone.set(it.content_hash, it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
register(diff:IDiffWatcher){
|
register(diff: IDiffWatcher) {
|
||||||
diff.on('create',(path)=>this.OnCreated(path))
|
diff.on('create', (path) => this.OnCreated(path))
|
||||||
.on('delete',(path)=>this.OnDeleted(path))
|
.on('delete', (path) => this.OnDeleted(path))
|
||||||
.on('change',(prev,cur)=>this.OnChanged(prev,cur));
|
.on('change', (prev, cur) => this.OnChanged(prev, cur));
|
||||||
}
|
}
|
||||||
private async OnDeleted(cpath: string){
|
private async OnDeleted(cpath: string) {
|
||||||
const basepath = dirname(cpath);
|
const basepath = dirname(cpath);
|
||||||
const filename = basename(cpath);
|
const filename = basename(cpath);
|
||||||
console.log("deleted ",cpath);
|
console.log("deleted ", cpath);
|
||||||
//if it wait to add, delete it from waiting list.
|
//if it wait to add, delete it from waiting list.
|
||||||
if(this.waiting_list.hasByPath(cpath)){
|
if (this.waiting_list.hasByPath(cpath)) {
|
||||||
this.waiting_list.deleteByPath(cpath);
|
this.waiting_list.deleteByPath(cpath);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const dbc = await this.doc_cntr.findByPath(basepath,filename);
|
const dbc = await this.doc_cntr.findByPath(basepath, filename);
|
||||||
//when there is no related content in db, ignore.
|
//when there is no related content in db, ignore.
|
||||||
if(dbc.length === 0) return;
|
if (dbc.length === 0) {
|
||||||
|
console.log("its not in waiting_list and db!!!: ", cpath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
const content_hash = dbc[0].content_hash;
|
const content_hash = dbc[0].content_hash;
|
||||||
// When a path is changed, it takes into account when the
|
// When a path is changed, it takes into account when the
|
||||||
// creation event occurs first and the deletion occurs, not
|
// creation event occurs first and the deletion occurs, not
|
||||||
// the change event.
|
// the change event.
|
||||||
const cf = this.waiting_list.getByHash(content_hash);
|
const cf = this.waiting_list.getByHash(content_hash);
|
||||||
if(cf){
|
if (cf) {
|
||||||
//if a path is changed, update the changed path.
|
//if a path is changed, update the changed path.
|
||||||
console.log("update path from", cpath,"to",cf.path);
|
console.log("update path from", cpath, "to", cf.path);
|
||||||
const newFilename = basename(cf.path);
|
const newFilename = basename(cf.path);
|
||||||
const newBasepath = dirname(cf.path);
|
const newBasepath = dirname(cf.path);
|
||||||
await this.waiting_list.deleteByHash(content_hash);
|
this.waiting_list.deleteByHash(content_hash);
|
||||||
await this.doc_cntr.update({
|
await this.doc_cntr.update({
|
||||||
id:dbc[0].id,
|
id: dbc[0].id,
|
||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
filename:newFilename,
|
filename: newFilename,
|
||||||
basepath:newBasepath,
|
basepath: newBasepath,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//invalidate db and add it to tombstone.
|
//invalidate db and add it to tombstone.
|
||||||
await this.doc_cntr.update({
|
await this.doc_cntr.update({
|
||||||
id:dbc[0].id,
|
id: dbc[0].id,
|
||||||
deleted_at: Date.now(),
|
deleted_at: Date.now(),
|
||||||
});
|
});
|
||||||
this.tombstone.set(dbc[0].content_hash, dbc[0]);
|
this.tombstone.set(dbc[0].content_hash, dbc[0]);
|
||||||
}
|
}
|
||||||
private async OnCreated(cpath:string){
|
private async OnCreated(cpath: string) {
|
||||||
const basepath = dirname(cpath);
|
const basepath = dirname(cpath);
|
||||||
const filename = basename(cpath);
|
const filename = basename(cpath);
|
||||||
console.log("createContentFile", cpath);
|
console.log("createContentFile", cpath);
|
||||||
const content = createContentFile(this.content_type,pathjoin(basepath,filename));
|
const content = createContentFile(this.content_type, cpath);
|
||||||
const hash = await content.getHash();
|
const hash = await content.getHash();
|
||||||
const c = this.tombstone.get(hash);
|
const c = this.tombstone.get(hash);
|
||||||
if(c !== undefined){
|
if (c !== undefined) {
|
||||||
this.doc_cntr.update({
|
await this.doc_cntr.update({
|
||||||
id: c.id,
|
id: c.id,
|
||||||
deleted_at: null,
|
deleted_at: null,
|
||||||
filename:filename,
|
filename: filename,
|
||||||
basepath:basepath
|
basepath: basepath
|
||||||
});
|
});
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
if(this.waiting_list.hasByHash(hash)){
|
if (this.waiting_list.hasByHash(hash)) {
|
||||||
console.log("Conflict!!!");
|
console.log("Hash Conflict!!!");
|
||||||
}
|
}
|
||||||
this.waiting_list.set(content);
|
this.waiting_list.set(content);
|
||||||
|
|
||||||
}
|
}
|
||||||
private async OnChanged(prev_path:string,cur_path:string){
|
private async OnChanged(prev_path: string, cur_path: string) {
|
||||||
const prev_basepath = dirname(prev_path);
|
const prev_basepath = dirname(prev_path);
|
||||||
const prev_filename = basename(prev_path);
|
const prev_filename = basename(prev_path);
|
||||||
const cur_basepath = dirname(cur_path);
|
const cur_basepath = dirname(cur_path);
|
||||||
const cur_filename = basename(cur_path);
|
const cur_filename = basename(cur_path);
|
||||||
const doc = await this.doc_cntr.findByPath(prev_basepath,prev_filename);
|
console.log("modify", cur_path, "from", prev_path);
|
||||||
await this.doc_cntr.update({...doc[0],
|
const c = this.waiting_list.getByPath(prev_path);
|
||||||
basepath:cur_basepath,
|
if(c !== undefined){
|
||||||
filename:cur_filename});
|
await this.waiting_list.delete(c);
|
||||||
|
const content = createContentFile(this.content_type, cur_path);
|
||||||
|
await this.waiting_list.set(content);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const doc = await this.doc_cntr.findByPath(prev_basepath, prev_filename);
|
||||||
|
|
||||||
|
if(doc.length === 0){
|
||||||
|
await this.OnCreated(cur_path);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.doc_cntr.update({
|
||||||
|
...doc[0],
|
||||||
|
basepath: cur_basepath,
|
||||||
|
filename: cur_filename
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -39,12 +39,15 @@ export class ContentList{
|
|||||||
async deleteByPath(p:string){
|
async deleteByPath(p:string){
|
||||||
const o = this.getByPath(p);
|
const o = this.getByPath(p);
|
||||||
if(o === undefined) return false;
|
if(o === undefined) return false;
|
||||||
return this.delete(o);
|
return await this.delete(o);
|
||||||
}
|
}
|
||||||
async deleteByHash(s:string){
|
deleteByHash(s:string){
|
||||||
const o = this.getByHash(s);
|
const o = this.getByHash(s);
|
||||||
if(o === undefined) return false;
|
if(o === undefined) return false;
|
||||||
return this.delete(o);
|
let r = true;
|
||||||
|
r = this.cl.delete(o.path) && r;
|
||||||
|
r = this.hl.delete(s) && r;
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
clear(){
|
clear(){
|
||||||
this.cl.clear();
|
this.cl.clear();
|
||||||
|
@ -73,6 +73,7 @@ const ContentQueryHandler = (controller : DocumentAccessor) => async (ctx: Conte
|
|||||||
}
|
}
|
||||||
const UpdateContentHandler = (controller : DocumentAccessor) => async (ctx: Context, next: Next) => {
|
const UpdateContentHandler = (controller : DocumentAccessor) => async (ctx: Context, next: Next) => {
|
||||||
const num = Number.parseInt(ctx.params['num']);
|
const num = Number.parseInt(ctx.params['num']);
|
||||||
|
|
||||||
if(ctx.request.type !== 'json'){
|
if(ctx.request.type !== 'json'){
|
||||||
return sendError(400,"update fail. invalid document type: it is not json.");
|
return sendError(400,"update fail. invalid document type: it is not json.");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user