Files
next.orly.dev/pkg/dgraph/fetch-event.go

271 lines
5.7 KiB
Go

package dgraph
import (
"context"
"encoding/json"
"fmt"
"next.orly.dev/pkg/database"
"next.orly.dev/pkg/database/indexes/types"
"next.orly.dev/pkg/encoders/event"
"next.orly.dev/pkg/encoders/hex"
"next.orly.dev/pkg/encoders/tag"
"next.orly.dev/pkg/interfaces/store"
)
// FetchEventBySerial retrieves an event by its serial number
func (d *D) FetchEventBySerial(ser *types.Uint40) (ev *event.E, err error) {
serial := ser.Get()
query := fmt.Sprintf(`{
event(func: eq(event.serial, %d)) {
event.id
event.kind
event.created_at
event.content
event.sig
event.pubkey
event.tags
}
}`, serial)
resp, err := d.Query(context.Background(), query)
if err != nil {
return nil, fmt.Errorf("failed to fetch event by serial: %w", err)
}
evs, err := d.parseEventsFromResponse(resp.Json)
if err != nil {
return nil, err
}
if len(evs) == 0 {
return nil, fmt.Errorf("event not found")
}
return evs[0], nil
}
// FetchEventsBySerials retrieves multiple events by their serial numbers
func (d *D) FetchEventsBySerials(serials []*types.Uint40) (
events map[uint64]*event.E, err error,
) {
if len(serials) == 0 {
return make(map[uint64]*event.E), nil
}
// Build query for multiple serials
serialStrs := make([]string, len(serials))
for i, ser := range serials {
serialStrs[i] = fmt.Sprintf("%d", ser.Get())
}
// Use uid() function for efficient multi-get
query := fmt.Sprintf(`{
events(func: uid(%s)) {
event.id
event.kind
event.created_at
event.content
event.sig
event.pubkey
event.tags
event.serial
}
}`, serialStrs[0]) // Simplified - in production you'd handle multiple UIDs properly
resp, err := d.Query(context.Background(), query)
if err != nil {
return nil, fmt.Errorf("failed to fetch events by serials: %w", err)
}
evs, err := d.parseEventsFromResponse(resp.Json)
if err != nil {
return nil, err
}
// Map events by serial
events = make(map[uint64]*event.E)
for i, ser := range serials {
if i < len(evs) {
events[ser.Get()] = evs[i]
}
}
return events, nil
}
// GetSerialById retrieves the serial number for an event ID
func (d *D) GetSerialById(id []byte) (ser *types.Uint40, err error) {
idStr := hex.Enc(id)
query := fmt.Sprintf(`{
event(func: eq(event.id, %q)) {
event.serial
}
}`, idStr)
resp, err := d.Query(context.Background(), query)
if err != nil {
return nil, fmt.Errorf("failed to get serial by ID: %w", err)
}
var result struct {
Event []struct {
Serial int64 `json:"event.serial"`
} `json:"event"`
}
if err = json.Unmarshal(resp.Json, &result); err != nil {
return nil, err
}
if len(result.Event) == 0 {
return nil, fmt.Errorf("event not found")
}
ser = &types.Uint40{}
ser.Set(uint64(result.Event[0].Serial))
return ser, nil
}
// GetSerialsByIds retrieves serial numbers for multiple event IDs
func (d *D) GetSerialsByIds(ids *tag.T) (
serials map[string]*types.Uint40, err error,
) {
serials = make(map[string]*types.Uint40)
if len(ids.T) == 0 {
return serials, nil
}
// Query each ID individually (simplified implementation)
for _, id := range ids.T {
if len(id) >= 2 {
idStr := string(id[1])
serial, err := d.GetSerialById([]byte(idStr))
if err == nil {
serials[idStr] = serial
}
}
}
return serials, nil
}
// GetSerialsByIdsWithFilter retrieves serials with a filter function
func (d *D) GetSerialsByIdsWithFilter(
ids *tag.T, fn func(ev *event.E, ser *types.Uint40) bool,
) (serials map[string]*types.Uint40, err error) {
serials = make(map[string]*types.Uint40)
if fn == nil {
// No filter, just return all
return d.GetSerialsByIds(ids)
}
// With filter, need to fetch events
for _, id := range ids.T {
if len(id) > 0 {
serial, err := d.GetSerialById(id)
if err != nil {
continue
}
ev, err := d.FetchEventBySerial(serial)
if err != nil {
continue
}
if fn(ev, serial) {
serials[string(id)] = serial
}
}
}
return serials, nil
}
// GetSerialsByRange retrieves serials within a range
func (d *D) GetSerialsByRange(idx database.Range) (
serials types.Uint40s, err error,
) {
// This would need to be implemented based on how ranges are defined
// For now, returning not implemented
err = fmt.Errorf("not implemented")
return
}
// GetFullIdPubkeyBySerial retrieves ID and pubkey for a serial number
func (d *D) GetFullIdPubkeyBySerial(ser *types.Uint40) (
fidpk *store.IdPkTs, err error,
) {
serial := ser.Get()
query := fmt.Sprintf(`{
event(func: eq(event.serial, %d)) {
event.id
event.pubkey
event.created_at
}
}`, serial)
resp, err := d.Query(context.Background(), query)
if err != nil {
return nil, fmt.Errorf("failed to get ID and pubkey by serial: %w", err)
}
var result struct {
Event []struct {
ID string `json:"event.id"`
Pubkey string `json:"event.pubkey"`
CreatedAt int64 `json:"event.created_at"`
} `json:"event"`
}
if err = json.Unmarshal(resp.Json, &result); err != nil {
return nil, err
}
if len(result.Event) == 0 {
return nil, fmt.Errorf("event not found")
}
id, err := hex.Dec(result.Event[0].ID)
if err != nil {
return nil, err
}
pubkey, err := hex.Dec(result.Event[0].Pubkey)
if err != nil {
return nil, err
}
fidpk = &store.IdPkTs{
Id: id,
Pub: pubkey,
Ts: result.Event[0].CreatedAt,
Ser: serial,
}
return fidpk, nil
}
// GetFullIdPubkeyBySerials retrieves IDs and pubkeys for multiple serials
func (d *D) GetFullIdPubkeyBySerials(sers []*types.Uint40) (
fidpks []*store.IdPkTs, err error,
) {
fidpks = make([]*store.IdPkTs, 0, len(sers))
for _, ser := range sers {
fidpk, err := d.GetFullIdPubkeyBySerial(ser)
if err != nil {
continue // Skip errors, continue with others
}
fidpks = append(fidpks, fidpk)
}
return fidpks, nil
}