Skip to content

Instantly share code, notes, and snippets.

@fiatjaf
Last active March 13, 2023 23:27
Show Gist options
  • Save fiatjaf/f4bd3d4604ca9ceef33add16d8b9206d to your computer and use it in GitHub Desktop.
Save fiatjaf/f4bd3d4604ca9ceef33add16d8b9206d to your computer and use it in GitHub Desktop.
getting an event payload from the strfry database directly from Go
package main
import (
"bytes"
"encoding/binary"
"encoding/hex"
"fmt"
"unsafe"
"github.com/bmatsuo/lmdb-go/lmdb"
"github.com/bmatsuo/lmdb-go/lmdbscan"
)
func main() {
initialize("/home/fiatjaf/comp/strfry/strfry-db/")
fmt.Println("=== by id ===")
fmt.Println(getEvent("ff80c31dc005d0ff6aa55daf2e15e9cd804aea781c85bafd17091587aeadaf37"))
fmt.Println("=== by pubkey and kind ===")
fmt.Println(getReplaceableEvent("feeec6c0c8aca208be1e1f19445e2b6b2a20ee774799b47088d0db7688dc5728", 0))
fmt.Println("=== iter metadata ===")
iterMetadata()
}
var (
env *lmdb.Env
eventsByIdIndexDbi lmdb.DBI
eventsByKindIndexDbi lmdb.DBI
eventsByPubkeyKindIndexDbi lmdb.DBI
eventsDbi lmdb.DBI
nativeEndian binary.ByteOrder
)
func initialize(lmdbPath string) {
buf := [2]byte{}
*(*uint16)(unsafe.Pointer(&buf[0])) = uint16(0xABCD)
switch buf {
case [2]byte{0xCD, 0xAB}:
nativeEndian = binary.LittleEndian
case [2]byte{0xAB, 0xCD}:
nativeEndian = binary.BigEndian
default:
panic("Could not determine native endianness.")
}
var err error
env, err = lmdb.NewEnv()
if err != nil {
panic(err)
}
env.SetMaxDBs(4)
err = env.Open(lmdbPath, 0, 0644)
if err != nil {
panic(err)
}
env.Update(func(txn *lmdb.Txn) error {
db1, err := txn.OpenDBI("rasgueadb_defaultDb__Event__id", 0)
if err != nil {
panic(err)
}
eventsByIdIndexDbi = db1
db2, err := txn.OpenDBI("rasgueadb_defaultDb__Event__pubkeyKind", 0)
if err != nil {
panic(err)
}
eventsByPubkeyKindIndexDbi = db2
db3, err := txn.OpenDBI("rasgueadb_defaultDb__Event__kind", 0)
if err != nil {
panic(err)
}
eventsByKindIndexDbi = db3
db4, err := txn.OpenDBI("rasgueadb_defaultDb__EventPayload", 0)
if err != nil {
panic(err)
}
eventsDbi = db4
return nil
})
}
func getEvent(id string) string {
var eventJson string
env.View(func(txn *lmdb.Txn) error {
txn.RawRead = true
eventId, err := hex.DecodeString(id)
if err != nil {
panic(err)
}
scanner := lmdbscan.New(txn, eventsByIdIndexDbi)
defer scanner.Close()
cursor := scanner.Cursor()
defer cursor.Close()
_, val, err := cursor.Get(eventId, nil, lmdb.SetRange)
if err != nil {
panic(err)
}
res, err := txn.Get(eventsDbi, val)
if err != nil {
return nil
}
eventJson = string(res[1:])
return nil
})
return eventJson
}
func getReplaceableEvent(pubkey string, kind int) string {
var eventJson string
env.View(func(txn *lmdb.Txn) error {
txn.RawRead = true
scanner := lmdbscan.New(txn, eventsByPubkeyKindIndexDbi)
defer scanner.Close()
cursor := scanner.Cursor()
defer cursor.Close()
pubkeyBytes, err := hex.DecodeString(pubkey)
if err != nil {
panic(err)
}
kindBytes := make([]byte, 8)
nativeEndian.PutUint64(kindBytes, uint64(kind))
keyBytes := append(pubkeyBytes, kindBytes...)
_, val, err := cursor.Get(keyBytes, nil, lmdb.SetRange)
if err != nil {
panic(err)
}
res, err := txn.Get(eventsDbi, val)
if err != nil {
return nil
}
eventJson = string(res[1:])
return nil
})
return eventJson
}
func iterMetadata() {
env.View(func(txn *lmdb.Txn) error {
txn.RawRead = true
scanner := lmdbscan.New(txn, eventsByKindIndexDbi)
defer scanner.Close()
cursor := scanner.Cursor()
defer cursor.Close()
kindBytes := make([]byte, 8)
for i := 0; i < 50; i++ {
k, v, err := cursor.Get(nil, nil, lmdb.NextNoDup)
if err != nil {
break
}
if !bytes.HasPrefix(k, kindBytes) {
break
}
res, err := txn.Get(eventsDbi, v)
if err != nil {
return nil
}
fmt.Println(string(res[1:]))
}
return nil
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment