You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.4 KiB
94 lines
2.4 KiB
package neo4j |
|
|
|
import ( |
|
"context" |
|
"fmt" |
|
"time" |
|
) |
|
|
|
// RecordEventAccess updates access tracking for an event in Neo4j. |
|
// This creates or updates an AccessTrack node for the event. |
|
func (n *N) RecordEventAccess(serial uint64, connectionID string) error { |
|
cypher := ` |
|
MERGE (a:AccessTrack {serial: $serial}) |
|
ON CREATE SET a.lastAccess = $now, a.count = 1 |
|
ON MATCH SET a.lastAccess = $now, a.count = a.count + 1` |
|
|
|
params := map[string]any{ |
|
"serial": int64(serial), // Neo4j uses int64 |
|
"now": time.Now().Unix(), |
|
} |
|
|
|
_, err := n.ExecuteWrite(context.Background(), cypher, params) |
|
if err != nil { |
|
return fmt.Errorf("failed to record event access: %w", err) |
|
} |
|
|
|
return nil |
|
} |
|
|
|
// GetEventAccessInfo returns access information for an event. |
|
func (n *N) GetEventAccessInfo(serial uint64) (lastAccess int64, accessCount uint32, err error) { |
|
cypher := "MATCH (a:AccessTrack {serial: $serial}) RETURN a.lastAccess AS lastAccess, a.count AS count" |
|
params := map[string]any{"serial": int64(serial)} |
|
|
|
result, err := n.ExecuteRead(context.Background(), cypher, params) |
|
if err != nil { |
|
return 0, 0, fmt.Errorf("failed to get event access info: %w", err) |
|
} |
|
|
|
ctx := context.Background() |
|
if result.Next(ctx) { |
|
record := result.Record() |
|
if record != nil { |
|
if la, found := record.Get("lastAccess"); found { |
|
if v, ok := la.(int64); ok { |
|
lastAccess = v |
|
} |
|
} |
|
if c, found := record.Get("count"); found { |
|
if v, ok := c.(int64); ok { |
|
accessCount = uint32(v) |
|
} |
|
} |
|
} |
|
} |
|
|
|
return lastAccess, accessCount, nil |
|
} |
|
|
|
// GetLeastAccessedEvents returns event serials sorted by coldness. |
|
func (n *N) GetLeastAccessedEvents(limit int, minAgeSec int64) (serials []uint64, err error) { |
|
cutoffTime := time.Now().Unix() - minAgeSec |
|
|
|
cypher := ` |
|
MATCH (a:AccessTrack) |
|
WHERE a.lastAccess < $cutoff |
|
RETURN a.serial AS serial, a.lastAccess AS lastAccess, a.count AS count |
|
ORDER BY (a.lastAccess + a.count * 3600) ASC |
|
LIMIT $limit` |
|
|
|
params := map[string]any{ |
|
"cutoff": cutoffTime, |
|
"limit": limit, |
|
} |
|
|
|
result, err := n.ExecuteRead(context.Background(), cypher, params) |
|
if err != nil { |
|
return nil, fmt.Errorf("failed to get least accessed events: %w", err) |
|
} |
|
|
|
ctx := context.Background() |
|
for result.Next(ctx) { |
|
record := result.Record() |
|
if record != nil { |
|
if s, found := record.Get("serial"); found { |
|
if v, ok := s.(int64); ok { |
|
serials = append(serials, uint64(v)) |
|
} |
|
} |
|
} |
|
} |
|
|
|
return serials, nil |
|
}
|
|
|