Index resolution metadata updates
This commit is contained in:
@@ -280,8 +280,23 @@ func cloneMetadata(metadata Metadata) Metadata {
|
||||
}
|
||||
|
||||
func applyResolutionMetadata(metadata *Metadata, resolved resolutionResult) {
|
||||
for _, snapshot := range resolved.snapshots {
|
||||
pointer := snapshot.change.Path.String()
|
||||
finalPaths := make(map[string]*document.Node)
|
||||
indexDocument(resolved.final, Path{}, finalPaths)
|
||||
snapshotCoverage, snapshotPointers := newResolutionCoverageIndexFromSnapshots(resolved.snapshots)
|
||||
var deltaCoverage pathPrefixIndex
|
||||
snapshotIDs := make([]int, len(resolved.deltas))
|
||||
for id, delta := range resolved.deltas {
|
||||
if delta.path.valid() {
|
||||
deltaCoverage.insert(delta.path.String(), id)
|
||||
}
|
||||
snapshotIDs[id] = -1
|
||||
if snapshotID, ok := snapshotCoverage.deepestCoveringID(delta.path); ok {
|
||||
snapshotIDs[id] = snapshotID
|
||||
}
|
||||
}
|
||||
|
||||
for snapshotID, snapshot := range resolved.snapshots {
|
||||
pointer := snapshotPointers[snapshotID]
|
||||
change := cloneChange(snapshot.change)
|
||||
if info, ok := metadata.fields[pointer]; ok {
|
||||
change.Previous = []Origin{cloneOrigin(info.Origin)}
|
||||
@@ -290,52 +305,40 @@ func applyResolutionMetadata(metadata *Metadata, resolved resolutionResult) {
|
||||
}
|
||||
metadata.history[pointer] = append(metadata.history[pointer], change)
|
||||
}
|
||||
appendResolutionDescendantHistory(metadata, resolved)
|
||||
for _, delta := range resolved.deltas {
|
||||
record := coveringResolutionSnapshot(resolved.snapshots, delta.path)
|
||||
if record == nil {
|
||||
continue
|
||||
}
|
||||
for pointer, info := range metadata.fields {
|
||||
path, err := ParsePath(pointer)
|
||||
if err != nil || !pathContains(delta.path, path) {
|
||||
continue
|
||||
}
|
||||
info.Origin = cloneOrigin(record.change.Origin)
|
||||
metadata.fields[pointer] = info
|
||||
}
|
||||
}
|
||||
refreshResolutionFields(metadata.fields, resolved.final, resolved.snapshots)
|
||||
|
||||
appendResolutionDescendantHistory(metadata, resolved.snapshots, snapshotPointers, finalPaths, &deltaCoverage, snapshotIDs)
|
||||
applyResolutionFieldOrigins(metadata.fields, resolved.snapshots, &deltaCoverage, snapshotIDs)
|
||||
refreshResolutionFields(metadata.fields, finalPaths, resolved.snapshots, snapshotCoverage)
|
||||
}
|
||||
|
||||
func appendResolutionDescendantHistory(metadata *Metadata, resolved resolutionResult) {
|
||||
finalPaths := make(map[string]*document.Node)
|
||||
indexDocument(resolved.final, Path{}, finalPaths)
|
||||
for _, delta := range resolved.deltas {
|
||||
record := coveringResolutionSnapshot(resolved.snapshots, delta.path)
|
||||
if record == nil {
|
||||
func appendResolutionDescendantHistory(metadata *Metadata, snapshots []resolutionSnapshot, snapshotPointers []string, finalPaths map[string]*document.Node, deltaIndex *pathPrefixIndex, snapshotIDs []int) {
|
||||
allPointers := make(map[string]struct{}, len(metadata.history)+len(finalPaths))
|
||||
for pointer := range metadata.history {
|
||||
if _, err := ParsePath(pointer); err == nil {
|
||||
allPointers[pointer] = struct{}{}
|
||||
}
|
||||
}
|
||||
for pointer := range finalPaths {
|
||||
allPointers[pointer] = struct{}{}
|
||||
}
|
||||
buckets := make([][]string, len(snapshotIDs))
|
||||
for pointer := range allPointers {
|
||||
deltaIndex.visitAncestors(pointer, func(deltaID int) {
|
||||
snapshotID := snapshotIDs[deltaID]
|
||||
if snapshotID < 0 || pointer == snapshotPointers[snapshotID] {
|
||||
return
|
||||
}
|
||||
buckets[deltaID] = append(buckets[deltaID], pointer)
|
||||
})
|
||||
}
|
||||
for deltaID, pointers := range buckets {
|
||||
snapshotID := snapshotIDs[deltaID]
|
||||
if snapshotID < 0 {
|
||||
continue
|
||||
}
|
||||
affected := make(map[string]bool)
|
||||
for pointer := range metadata.history {
|
||||
if path, err := ParsePath(pointer); err == nil && pathContains(delta.path, path) {
|
||||
affected[pointer] = true
|
||||
}
|
||||
}
|
||||
for pointer := range finalPaths {
|
||||
if path, err := ParsePath(pointer); err == nil && pathContains(delta.path, path) {
|
||||
affected[pointer] = true
|
||||
}
|
||||
}
|
||||
pointers := make([]string, 0, len(affected))
|
||||
for pointer := range affected {
|
||||
if pointer != record.change.Path.String() {
|
||||
pointers = append(pointers, pointer)
|
||||
}
|
||||
}
|
||||
slices.Sort(pointers)
|
||||
for _, pointer := range pointers {
|
||||
change := cloneChange(record.change)
|
||||
change := cloneChange(snapshots[snapshotID].change)
|
||||
if info, ok := metadata.fields[pointer]; ok {
|
||||
change.Previous = []Origin{cloneOrigin(info.Origin)}
|
||||
}
|
||||
@@ -344,20 +347,33 @@ func appendResolutionDescendantHistory(metadata *Metadata, resolved resolutionRe
|
||||
}
|
||||
}
|
||||
|
||||
func coveringResolutionSnapshot(snapshots []resolutionSnapshot, path Path) *resolutionSnapshot {
|
||||
var covering *resolutionSnapshot
|
||||
for index := range snapshots {
|
||||
snapshot := &snapshots[index]
|
||||
if pathContains(snapshot.change.Path, path) && (covering == nil || len(snapshot.change.Path.segments) > len(covering.change.Path.segments)) {
|
||||
covering = snapshot
|
||||
func applyResolutionFieldOrigins(fields map[string]FieldInfo, snapshots []resolutionSnapshot, deltaIndex *pathPrefixIndex, snapshotIDs []int) {
|
||||
buckets := make([][]string, len(snapshotIDs))
|
||||
for pointer := range fields {
|
||||
if _, err := ParsePath(pointer); err != nil {
|
||||
continue
|
||||
}
|
||||
deltaIndex.visitAncestors(pointer, func(deltaID int) {
|
||||
if snapshotIDs[deltaID] >= 0 {
|
||||
buckets[deltaID] = append(buckets[deltaID], pointer)
|
||||
}
|
||||
})
|
||||
}
|
||||
for deltaID, pointers := range buckets {
|
||||
snapshotID := snapshotIDs[deltaID]
|
||||
if snapshotID < 0 {
|
||||
continue
|
||||
}
|
||||
origin := snapshots[snapshotID].change.Origin
|
||||
for _, pointer := range pointers {
|
||||
info := fields[pointer]
|
||||
info.Origin = cloneOrigin(origin)
|
||||
fields[pointer] = info
|
||||
}
|
||||
}
|
||||
return covering
|
||||
}
|
||||
|
||||
func refreshResolutionFields(fields map[string]FieldInfo, final *document.Node, snapshots []resolutionSnapshot) {
|
||||
finalPaths := make(map[string]*document.Node)
|
||||
indexDocument(final, Path{}, finalPaths)
|
||||
func refreshResolutionFields(fields map[string]FieldInfo, finalPaths map[string]*document.Node, snapshots []resolutionSnapshot, snapshotCoverage *resolutionCoverageIndex) {
|
||||
for pointer := range fields {
|
||||
if _, ok := finalPaths[pointer]; !ok {
|
||||
delete(fields, pointer)
|
||||
@@ -370,10 +386,8 @@ func refreshResolutionFields(fields map[string]FieldInfo, final *document.Node,
|
||||
continue
|
||||
}
|
||||
origin := Origin{Layer: LayerResolution}
|
||||
if path, err := ParsePath(pointer); err == nil {
|
||||
if covering := coveringResolutionSnapshot(snapshots, path); covering != nil {
|
||||
origin = cloneOrigin(covering.change.Origin)
|
||||
}
|
||||
if snapshotID, ok := snapshotCoverage.deepestCoveringPointerID(pointer); ok {
|
||||
origin = cloneOrigin(snapshots[snapshotID].change.Origin)
|
||||
}
|
||||
fields[pointer] = FieldInfo{Null: node.Kind == document.Null, Origin: origin}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user