Files
crawler_v2/pkg/graph/graph.go
2025-07-10 17:44:46 +02:00

105 lines
2.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// The graph package defines the fundamental structures (e.g. [Node], [Delta])
// that are used across packages.
package graph
import (
"errors"
"time"
"github.com/pippellia-btc/slicex"
)
const (
// types of status
StatusActive string = "active" // meaning, we generate random walks for this node
StatusInactive string = "inactive"
// internal record kinds
Addition int = -3
Promotion int = -2
Demotion int = -1
)
var (
ErrNodeNotFound = errors.New("node not found")
ErrNodeAlreadyExists = errors.New("node already exists")
)
type ID string
func (id ID) MarshalBinary() ([]byte, error) { return []byte(id), nil }
// Node contains the metadata about a node, including a collection of Records.
type Node struct {
ID ID
Pubkey string
Status string // either [StatusActive] or [StatusInactive]
Records []Record
}
// Record contains the timestamp of a node update.
type Record struct {
Kind int // either [Addition], [Promotion] or [Demotion]
Timestamp time.Time
}
func (n *Node) Addition() (time.Time, bool) { return n.find(Addition) }
func (n *Node) Promotion() (time.Time, bool) { return n.find(Promotion) }
func (n *Node) Demotion() (time.Time, bool) { return n.find(Demotion) }
func (n *Node) find(kind int) (time.Time, bool) {
for _, record := range n.Records {
if record.Kind == kind {
return record.Timestamp, true
}
}
return time.Time{}, false
}
// Delta represents updates to apply to a Node.
// Add and Remove contain node IDs to add to or remove from the nodes relationships (e.g., follow list).
type Delta struct {
Kind int
Node ID
Remove []ID
Keep []ID
Add []ID
}
// NewDelta returns a delta by computing the relationships to remove, keep and add.
func NewDelta(kind int, node ID, old, new []ID) Delta {
delta := Delta{
Kind: kind,
Node: node,
}
delta.Remove, delta.Keep, delta.Add = slicex.Partition(old, new)
return delta
}
// Size returns the number of relationships changed by delta
func (d Delta) Size() int {
return len(d.Remove) + len(d.Add)
}
// Old returns the old state of the delta
func (d Delta) Old() []ID {
return append(d.Keep, d.Remove...)
}
// New returns the new state of the delta
func (d Delta) New() []ID {
return append(d.Keep, d.Add...)
}
// Inverse of the delta. If a delta and it's inverse are applied, the graph returns to its original state.
func (d Delta) Inverse() Delta {
return Delta{
Kind: d.Kind,
Node: d.Node,
Keep: d.Keep,
Remove: d.Add,
Add: d.Remove,
}
}