mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-10-05 19:28:25 +00:00
refactor(quartz): move FTS toggle into IndexingStrategy
Fold the full-text-search on/off switch into `IndexingStrategy` as `indexFullTextSearch` (default `true`) instead of a separate top-level `enableFullTextSearch` constructor param on `EventStore`/`SQLiteEventStore`. `IndexingStrategy` is already the single place that decides which indexes the store builds — every field is a per-index toggle with a size/speed tradeoff, and `QueryBuilder` already receives it — so FTS, being just another index, belongs there rather than split across two config surfaces. Behaviour is unchanged: the module's no-op path and the QueryBuilder "search matches nothing" guards now read the flag via the strategy. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BjzUpY8H31c7ux669zytWg
This commit is contained in:
@@ -76,12 +76,15 @@ val store = EventStore(
|
||||
indexTagsByCreatedAtAlone = false,
|
||||
indexTagsWithKindAndPubkey = false,
|
||||
useAndIndexIdOnOrderBy = false,
|
||||
indexFullTextSearch = true,
|
||||
),
|
||||
)
|
||||
```
|
||||
|
||||
By default, all single-letter tags with values are indexed. Override `shouldIndex(kind, tag)` for custom behavior. More indexes = faster queries but larger database.
|
||||
|
||||
`indexFullTextSearch` defaults to `true` and controls the NIP-50 full-text index (`event_fts`). Set it to `false` when search is served elsewhere (e.g. a Vespa backend, or a `SearchEventSource` as shown below): inserts skip the FTS tokenization cost, no `event_fts` table/trigger is created, and any filter carrying a non-empty `search` term returns no matches.
|
||||
|
||||
## Non-Storage Relays (search, redirector, computed)
|
||||
|
||||
A relay's job is to *answer REQs*. When the answer doesn't come from a stored
|
||||
|
||||
+1
-9
@@ -38,16 +38,8 @@ class EventStore(
|
||||
dbName: String? = "events.db",
|
||||
override val relay: NormalizedRelayUrl? = "wss://quartz.local/".normalizeRelayUrl(),
|
||||
val indexStrategy: IndexingStrategy = DefaultIndexingStrategy(),
|
||||
/**
|
||||
* When `false`, NIP-50 full-text search indexing is turned off: no
|
||||
* `event_fts` table or delete trigger is created, inserts skip the
|
||||
* FTS tokenization cost, and `search` filters return no matches.
|
||||
* Use for stores that never serve search from SQLite (e.g. a relay
|
||||
* that offloads NIP-50 to an external engine like Vespa).
|
||||
*/
|
||||
val enableFullTextSearch: Boolean = true,
|
||||
) : IEventStore {
|
||||
val store = SQLiteEventStore(BundledSQLiteDriver(), dbName, relay, indexStrategy, enableFullTextSearch = enableFullTextSearch)
|
||||
val store = SQLiteEventStore(BundledSQLiteDriver(), dbName, relay, indexStrategy)
|
||||
|
||||
override suspend fun insert(event: Event) = store.insertEvent(event)
|
||||
|
||||
|
||||
+16
@@ -81,6 +81,21 @@ interface IndexingStrategy {
|
||||
*/
|
||||
val useAndIndexIdOnOrderBy: Boolean
|
||||
|
||||
/**
|
||||
* Maintain the NIP-50 full-text search index (`event_fts`).
|
||||
*
|
||||
* Unlike the other flags this defaults to **on**: search is a core
|
||||
* feature and every searchable event is tokenized into an FTS virtual
|
||||
* table on insert, with an `AFTER DELETE` trigger keeping it in sync.
|
||||
*
|
||||
* Turn it **off** when this store never serves search from SQLite —
|
||||
* e.g. a relay that offloads NIP-50 to an external engine like Vespa.
|
||||
* With it off, no `event_fts` table or trigger is created, inserts
|
||||
* skip the tokenization cost, deletes skip the trigger, and any filter
|
||||
* carrying a non-empty `search` term returns no matches.
|
||||
*/
|
||||
val indexFullTextSearch: Boolean
|
||||
|
||||
fun shouldIndex(
|
||||
kind: Int,
|
||||
tag: Tag,
|
||||
@@ -95,6 +110,7 @@ class DefaultIndexingStrategy(
|
||||
override val indexTagsByCreatedAtAlone: Boolean = false,
|
||||
override val indexTagsWithKindAndPubkey: Boolean = false,
|
||||
override val useAndIndexIdOnOrderBy: Boolean = false,
|
||||
override val indexFullTextSearch: Boolean = true,
|
||||
) : IndexingStrategy {
|
||||
override fun shouldIndex(
|
||||
kind: Int,
|
||||
|
||||
+8
-2
@@ -195,10 +195,16 @@ FTS indexing has a write-time cost: every inserted `SearchableEvent` is
|
||||
tokenized into the `event_fts` virtual table, and an `AFTER DELETE`
|
||||
trigger keeps that table in sync on every deletion. If you never serve
|
||||
NIP-50 search from this store — e.g. a relay that offloads search to an
|
||||
external engine like Vespa — pass `enableFullTextSearch = false`:
|
||||
external engine like Vespa — turn it off through the `IndexingStrategy`,
|
||||
alongside the other per-index toggles. `indexFullTextSearch` defaults to
|
||||
`true` (search is a core feature); set it to `false`:
|
||||
|
||||
```kotlin
|
||||
val eventStore = EventStore("dbname.db", relayUrlIdentifier, enableFullTextSearch = false)
|
||||
val eventStore = EventStore(
|
||||
"dbname.db",
|
||||
relayUrlIdentifier,
|
||||
indexStrategy = DefaultIndexingStrategy(indexFullTextSearch = false),
|
||||
)
|
||||
```
|
||||
|
||||
With FTS off:
|
||||
|
||||
+1
-9
@@ -43,14 +43,6 @@ class SQLiteEventStore(
|
||||
val relay: NormalizedRelayUrl? = null,
|
||||
val indexStrategy: IndexingStrategy = DefaultIndexingStrategy(),
|
||||
val numReaders: Int = 4,
|
||||
/**
|
||||
* When `false`, NIP-50 full-text search indexing is turned off: no
|
||||
* `event_fts` table or delete trigger is created, inserts skip the
|
||||
* FTS tokenization cost, and `search` filters return no matches.
|
||||
* Use for stores that never serve search from SQLite (e.g. a relay
|
||||
* that offloads NIP-50 to an external engine like Vespa).
|
||||
*/
|
||||
val enableFullTextSearch: Boolean = true,
|
||||
) {
|
||||
companion object {
|
||||
const val DATABASE_VERSION = 2
|
||||
@@ -58,7 +50,7 @@ class SQLiteEventStore(
|
||||
|
||||
val seedModule = SeedModule()
|
||||
|
||||
val fullTextSearchModule = FullTextSearchModule(enableFullTextSearch)
|
||||
val fullTextSearchModule = FullTextSearchModule(indexStrategy.indexFullTextSearch)
|
||||
val eventIndexModule =
|
||||
EventIndexesModule(
|
||||
seedModule::hasher,
|
||||
|
||||
+7
-2
@@ -35,7 +35,8 @@ import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
/**
|
||||
* Exercises a [SQLiteEventStore] created with `enableFullTextSearch = false`.
|
||||
* Exercises a [SQLiteEventStore] built with an [IndexingStrategy] whose
|
||||
* `indexFullTextSearch` is `false`.
|
||||
*
|
||||
* The store must behave exactly like a normal store for every non-search
|
||||
* operation while (a) never creating the `event_fts` table or its delete
|
||||
@@ -51,7 +52,11 @@ class NoFullTextSearchTest {
|
||||
Secp256k1Instance
|
||||
}
|
||||
|
||||
private fun store() = SQLiteEventStore(dbName = null, enableFullTextSearch = false)
|
||||
private fun store() =
|
||||
SQLiteEventStore(
|
||||
dbName = null,
|
||||
indexStrategy = DefaultIndexingStrategy(indexFullTextSearch = false),
|
||||
)
|
||||
|
||||
private fun objectExists(
|
||||
db: SQLiteConnection,
|
||||
|
||||
Reference in New Issue
Block a user