appName: strfry features: ssl: true config: true onAppStartup: true db: true customLMDBSetup: true flatbuffers: true websockets: true templar: true flatBuffers: | include "../fbs/nostr-index.fbs"; includes: | inline std::string_view sv(const NostrIndex::Fixed32Bytes *f) { return std::string_view((const char *)f->val()->data(), 32); } tables: ## DB meta-data. Single entry, with id = 1 Meta: fields: - name: dbVersion - name: endianness ## Meta-info of nostr events, suitable for indexing ## Primary key is auto-incremented, called "levId" for Local EVent ID Event: fields: - name: receivedAt # microseconds - name: flat type: ubytes nestedFlat: NostrIndex.Event - name: sourceType - name: sourceInfo type: ubytes indices: created_at: integer: true receivedAt: integer: true id: comparator: StringUint64 pubkey: comparator: StringUint64 kind: comparator: Uint64Uint64 pubkeyKind: comparator: StringUint64Uint64 tag: comparator: StringUint64 multi: true deletion: # eventId, pubkey multi: true expiration: # unix timestamp, value of 1 is special-case for ephemeral event integer: true multi: true replace: # pubkey, d-tag, kind multi: true indexPrelude: | auto *flat = v.flat_nested(); created_at = flat->created_at(); uint64_t indexTime = *created_at; receivedAt = v.receivedAt(); id = makeKey_StringUint64(sv(flat->id()), indexTime); pubkey = makeKey_StringUint64(sv(flat->pubkey()), indexTime); kind = makeKey_Uint64Uint64(flat->kind(), indexTime); pubkeyKind = makeKey_StringUint64Uint64(sv(flat->pubkey()), flat->kind(), indexTime); for (const auto &tagPair : *(flat->tagsGeneral())) { auto tagName = (char)tagPair->key(); auto tagVal = sv(tagPair->val()); tag.push_back(makeKey_StringUint64(std::string(1, tagName) + std::string(tagVal), indexTime)); if (tagName == 'd' && replace.size() == 0) { replace.push_back(makeKey_StringUint64(std::string(sv(flat->pubkey())) + std::string(tagVal), flat->kind())); } } for (const auto &tagPair : *(flat->tagsFixed32())) { auto tagName = (char)tagPair->key(); auto tagVal = sv(tagPair->val()); tag.push_back(makeKey_StringUint64(std::string(1, tagName) + std::string(tagVal), indexTime)); if (flat->kind() == 5 && tagName == 'e') deletion.push_back(std::string(tagVal) + std::string(sv(flat->pubkey()))); } if (flat->expiration() != 0) { expiration.push_back(flat->expiration()); } CompressionDictionary: fields: - name: dict type: ubytes tablesRaw: ## Raw nostr event JSON, possibly compressed ## keys are levIds ## vals are prefixed with a type byte: ## 0: no compression, payload follows ## 1: zstd compression. Followed by Dictionary ID (native endian uint32) then compressed payload EventPayload: flags: 'MDB_INTEGERKEY' config: - name: db desc: "Directory that contains the strfry LMDB database" default: "./strfry-db/" noReload: true - name: dbParams__maxreaders desc: "Maximum number of threads/processes that can simultaneously have LMDB transactions open" default: 256 noReload: true - name: dbParams__mapsize desc: "Size of mmap() to use when loading LMDB (default is 10TB, does *not* correspond to disk-space used)" default: 10995116277760 noReload: true - name: dbParams__noReadAhead desc: "Disables read-ahead when accessing the LMDB mapping. Reduces IO activity when DB size is larger than RAM." default: false noReload: true - name: events__maxEventSize desc: "Maximum size of normalised JSON, in bytes" default: 65536 - name: events__rejectEventsNewerThanSeconds desc: "Events newer than this will be rejected" default: 900 # 15 mins - name: events__rejectEventsOlderThanSeconds desc: "Events older than this will be rejected" default: 94608000 # 3 years - name: events__rejectEphemeralEventsOlderThanSeconds desc: "Ephemeral events older than this will be rejected" default: 60 - name: events__ephemeralEventsLifetimeSeconds desc: "Ephemeral events will be deleted from the DB when older than this" default: 300 - name: events__maxNumTags desc: "Maximum number of tags allowed" default: 2000 - name: events__maxTagValSize desc: "Maximum size for tag values, in bytes" default: 1024