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.
270 lines
5.7 KiB
270 lines
5.7 KiB
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 |
|
}
|
|
|