Skip to content

Commit ca77653

Browse files
committed
fix: Refactor and speed up Diff.findChain
Signed-off-by: Marcel Klehr <mklehr@gmx.net>
1 parent 0b65ac9 commit ca77653

1 file changed

Lines changed: 46 additions & 33 deletions

File tree

src/lib/Diff.ts

Lines changed: 46 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -106,57 +106,70 @@ export default class Diff<L1 extends TItemLocation, L2 extends TItemLocation, A
106106
this.actions
107107
)
108108
}
109+
110+
static contains(mappingsSnapshot: MappingSnapshot, item1: TItem<TItemLocation>, item2: TItem<TItemLocation>, itemTree: Folder<TItemLocation>, cache: Record<string, boolean>): boolean {
111+
const cacheKey = 'contains:' + Mappings.mapId(mappingsSnapshot, item2, ItemLocation.LOCAL) + ':' + Mappings.mapId(mappingsSnapshot, item2, ItemLocation.SERVER) +
112+
'-' + Mappings.mapId(mappingsSnapshot, item1, ItemLocation.LOCAL) + ':' + Mappings.mapId(mappingsSnapshot, item1, ItemLocation.SERVER)
113+
if (typeof cache[cacheKey] !== 'undefined') {
114+
return cache[cacheKey]
115+
}
116+
const item1InTree = itemTree.findItem(item1.type, Mappings.mapId(mappingsSnapshot, item1, itemTree.location))
117+
if (
118+
// target action payload contains item2's parent
119+
item1.findItem(ItemType.FOLDER,
120+
Mappings.mapParentId(mappingsSnapshot, item2, item1.location)) ||
121+
// target action payload contains item2
122+
item1.findItem(ItemType.FOLDER,
123+
Mappings.mapId(mappingsSnapshot, item2, item1.location)) ||
124+
// or target in tree contains item2's parent
125+
(item1InTree && item1InTree.findItem(ItemType.FOLDER, Mappings.mapParentId(mappingsSnapshot, item2, itemTree.location))) ||
126+
// or target in tree contains item2
127+
(item1InTree && item1InTree.findItem(item2.type, Mappings.mapId(mappingsSnapshot, item2, itemTree.location))) ||
128+
// or target action payload is the item2
129+
Mappings.mapId(mappingsSnapshot, item1, item2.location) === item2.id ||
130+
// or target action payload is the item2's parent
131+
Mappings.mapId(mappingsSnapshot, item1, item2.location) === item2.parentId ||
132+
// or target action payload is the item2
133+
Mappings.mapId(mappingsSnapshot, item2, item1.location) === item1.id ||
134+
// or target action payload is the item2s parent
135+
Mappings.mapParentId(mappingsSnapshot, item2, item1.location) === item1.id
136+
) {
137+
cache[cacheKey] = true
138+
return true
139+
}
140+
cache[cacheKey] = false
141+
return false
142+
}
109143

110144
static findChain(
111145
mappingsSnapshot: MappingSnapshot,
112146
actions: Action<TItemLocation, TItemLocation>[],
113147
itemTree: Folder<TItemLocation>,
114148
currentItem: TItem<TItemLocation>,
115149
targetAction: Action<TItemLocation, TItemLocation>,
150+
cache: Record<string, boolean> = {},
116151
chain: Action<TItemLocation, TItemLocation>[] = []
117152
): boolean {
118-
const targetItemInTree = itemTree.findItem(targetAction.payload.type, Mappings.mapId(mappingsSnapshot, targetAction.payload, itemTree.location))
119-
if (
120-
// target action payload contains currentItem's parent
121-
targetAction.payload.findItem(ItemType.FOLDER,
122-
Mappings.mapParentId(mappingsSnapshot, currentItem, targetAction.payload.location)) ||
123-
// target action payload contains currentItem
124-
targetAction.payload.findItem(ItemType.FOLDER,
125-
Mappings.mapId(mappingsSnapshot, currentItem, targetAction.payload.location)) ||
126-
// or target in tree contains currentItem
127-
(targetItemInTree && targetItemInTree.findItem(ItemType.FOLDER, Mappings.mapParentId(mappingsSnapshot, currentItem, itemTree.location))) ||
128-
// or target action payload is the currentItem
129-
Mappings.mapId(mappingsSnapshot, targetAction.payload, currentItem.location) === currentItem.id ||
130-
// or target action payload is the currentItem's parent
131-
Mappings.mapId(mappingsSnapshot, targetAction.payload, currentItem.location) === currentItem.parentId ||
132-
// or target action payload is the currentItem
133-
Mappings.mapId(mappingsSnapshot, currentItem, targetAction.payload.location) === targetAction.payload.id ||
134-
// or target action payload is the currentItems parent
135-
Mappings.mapParentId(mappingsSnapshot, currentItem, targetAction.payload.location) === targetAction.payload.id
136-
) {
153+
154+
const cacheKey = 'hasChain:' + Mappings.mapId(mappingsSnapshot, currentItem, ItemLocation.LOCAL) + ':' + Mappings.mapId(mappingsSnapshot, currentItem, ItemLocation.SERVER) + '-' + Mappings.mapId(mappingsSnapshot, targetAction.payload, ItemLocation.LOCAL) + ':' + Mappings.mapId(mappingsSnapshot, targetAction.payload, ItemLocation.SERVER)
155+
if (typeof cache[cacheKey] !== 'undefined') {
156+
return cache[cacheKey]
157+
}
158+
if (Diff.contains(mappingsSnapshot, targetAction.payload, currentItem, itemTree, cache)) {
159+
cache[cacheKey] = true
137160
return true
138161
}
139-
const newCurrentActions = actions.filter(targetAction =>
140-
!chain.includes(targetAction) && (
141-
targetAction.payload.findItem(ItemType.FOLDER, Mappings.mapParentId(mappingsSnapshot, currentItem, targetAction.payload.location)) ||
142-
targetAction.payload.findItem(currentItem.type, Mappings.mapId(mappingsSnapshot, currentItem, targetAction.payload.location)) ||
143-
(
144-
itemTree.findFolder(Mappings.mapId(mappingsSnapshot, targetAction.payload, itemTree.location)) &&
145-
itemTree.findFolder(Mappings.mapId(mappingsSnapshot, targetAction.payload, itemTree.location)).findFolder(Mappings.mapParentId(mappingsSnapshot, currentItem, itemTree.location))
146-
) ||
147-
(
148-
itemTree.findFolder(Mappings.mapId(mappingsSnapshot, targetAction.payload, itemTree.location)) &&
149-
itemTree.findFolder(Mappings.mapId(mappingsSnapshot, targetAction.payload, itemTree.location)).findItem(currentItem.type, Mappings.mapId(mappingsSnapshot, currentItem, itemTree.location))
150-
)
151-
)
162+
const newCurrentActions = actions.filter(newTargetAction =>
163+
!chain.includes(newTargetAction) && Diff.contains(mappingsSnapshot, newTargetAction.payload, currentItem, itemTree, cache)
152164
)
153165
if (newCurrentActions.length) {
154166
for (const newCurrentAction of newCurrentActions) {
155-
if (Diff.findChain(mappingsSnapshot, actions, itemTree, newCurrentAction.payload, targetAction, [...chain, newCurrentAction])) {
167+
if (Diff.findChain(mappingsSnapshot, actions, itemTree, newCurrentAction.payload, targetAction, cache,[...chain, newCurrentAction])) {
156168
return true
157169
}
158170
}
159171
}
172+
cache[cacheKey] = false
160173
return false
161174
}
162175

0 commit comments

Comments
 (0)