mirror of
https://github.com/MarginaliaSearch/MarginaliaSearch.git
synced 2025-02-23 13:09:00 +00:00
(query-service) Provide delegate of IndexApi's query functionality.
This is an intermediate step in the process of introducing the query-service as a proxy between search and index.
This commit is contained in:
parent
89c6d85f2f
commit
94c882af7d
32
code/api/query-api/build.gradle
Normal file
32
code/api/query-api/build.gradle
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
plugins {
|
||||||
|
id 'java'
|
||||||
|
id 'jvm-test-suite'
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(21))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation project(':code:common:model')
|
||||||
|
implementation project(':code:api:index-api')
|
||||||
|
implementation project(':code:common:config')
|
||||||
|
implementation project(':code:libraries:message-queue')
|
||||||
|
implementation project(':code:common:service-discovery')
|
||||||
|
implementation project(':code:common:service-client')
|
||||||
|
|
||||||
|
implementation libs.bundles.slf4j
|
||||||
|
|
||||||
|
implementation libs.prometheus
|
||||||
|
implementation libs.notnull
|
||||||
|
implementation libs.guice
|
||||||
|
implementation libs.rxjava
|
||||||
|
implementation libs.gson
|
||||||
|
|
||||||
|
testImplementation libs.bundles.slf4j.test
|
||||||
|
testImplementation libs.bundles.junit
|
||||||
|
testImplementation libs.mockito
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,56 @@
|
|||||||
|
package nu.marginalia.query.client;
|
||||||
|
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import io.prometheus.client.Summary;
|
||||||
|
import io.reactivex.rxjava3.core.Observable;
|
||||||
|
import nu.marginalia.WmsaHome;
|
||||||
|
import nu.marginalia.client.AbstractDynamicClient;
|
||||||
|
import nu.marginalia.client.Context;
|
||||||
|
import nu.marginalia.index.client.model.query.SearchSpecification;
|
||||||
|
import nu.marginalia.index.client.model.results.SearchResultSet;
|
||||||
|
import nu.marginalia.model.gson.GsonFactory;
|
||||||
|
import nu.marginalia.mq.MessageQueueFactory;
|
||||||
|
import nu.marginalia.mq.outbox.MqOutbox;
|
||||||
|
import nu.marginalia.service.descriptor.ServiceDescriptors;
|
||||||
|
import nu.marginalia.service.id.ServiceId;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.annotation.CheckReturnValue;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class QueryClient extends AbstractDynamicClient {
|
||||||
|
|
||||||
|
private static final Summary wmsa_search_index_api_delegate_time = Summary.build().name("wmsa_search_index_api_delegate_time").help("-").register();
|
||||||
|
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
|
private final MqOutbox outbox;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public QueryClient(ServiceDescriptors descriptors,
|
||||||
|
MessageQueueFactory messageQueueFactory) {
|
||||||
|
|
||||||
|
super(descriptors.forId(ServiceId.Query), WmsaHome.getHostsFile(), GsonFactory::get);
|
||||||
|
|
||||||
|
String inboxName = ServiceId.Query.name + ":" + "0";
|
||||||
|
String outboxName = System.getProperty("service-name", UUID.randomUUID().toString());
|
||||||
|
|
||||||
|
outbox = messageQueueFactory.createOutbox(inboxName, outboxName, UUID.randomUUID());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Delegate an Index API style query directly to the index service */
|
||||||
|
@CheckReturnValue
|
||||||
|
public SearchResultSet delegate(Context ctx, SearchSpecification specs) {
|
||||||
|
return wmsa_search_index_api_delegate_time.time(
|
||||||
|
() -> this.postGet(ctx, "/delegate/", specs, SearchResultSet.class).blockingFirst()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
public MqOutbox outbox() {
|
||||||
|
return outbox;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -26,11 +26,14 @@ dependencies {
|
|||||||
implementation project(':code:common:model')
|
implementation project(':code:common:model')
|
||||||
implementation project(':code:common:db')
|
implementation project(':code:common:db')
|
||||||
implementation project(':code:common:service')
|
implementation project(':code:common:service')
|
||||||
|
implementation project(':code:common:service-client')
|
||||||
implementation project(':code:api:index-api')
|
implementation project(':code:api:index-api')
|
||||||
implementation project(':code:common:service-discovery')
|
implementation project(':code:common:service-discovery')
|
||||||
|
|
||||||
implementation libs.bundles.slf4j
|
implementation libs.bundles.slf4j
|
||||||
|
|
||||||
|
implementation libs.spark
|
||||||
|
implementation libs.gson
|
||||||
implementation libs.prometheus
|
implementation libs.prometheus
|
||||||
implementation libs.notnull
|
implementation libs.notnull
|
||||||
implementation libs.guice
|
implementation libs.guice
|
||||||
|
@ -1,6 +1,11 @@
|
|||||||
package nu.marginalia.query;
|
package nu.marginalia.query;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
|
import nu.marginalia.model.gson.GsonFactory;
|
||||||
|
|
||||||
public class QueryModule extends AbstractModule {
|
public class QueryModule extends AbstractModule {
|
||||||
|
public void configure() {
|
||||||
|
bind(Gson.class).toProvider(GsonFactory::get);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,41 @@
|
|||||||
package nu.marginalia.query;
|
package nu.marginalia.query;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
import nu.marginalia.client.Context;
|
||||||
|
import nu.marginalia.index.client.IndexClient;
|
||||||
|
import nu.marginalia.index.client.model.query.SearchSpecification;
|
||||||
|
import nu.marginalia.index.client.model.results.SearchResultSet;
|
||||||
import nu.marginalia.service.server.BaseServiceParams;
|
import nu.marginalia.service.server.BaseServiceParams;
|
||||||
import nu.marginalia.service.server.Service;
|
import nu.marginalia.service.server.Service;
|
||||||
|
import spark.Request;
|
||||||
|
import spark.Response;
|
||||||
|
import spark.Spark;
|
||||||
|
|
||||||
public class QueryService extends Service {
|
public class QueryService extends Service {
|
||||||
|
|
||||||
|
private final IndexClient indexClient;
|
||||||
|
private final Gson gson;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public QueryService(BaseServiceParams params) {
|
public QueryService(BaseServiceParams params,
|
||||||
|
IndexClient indexClient,
|
||||||
|
Gson gson)
|
||||||
|
{
|
||||||
super(params);
|
super(params);
|
||||||
|
this.indexClient = indexClient;
|
||||||
|
this.gson = gson;
|
||||||
|
|
||||||
|
Spark.post("/delegate/", this::delegateToIndex, gson::toJson);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private SearchResultSet delegateToIndex(Request request, Response response) {
|
||||||
|
String json = request.body();
|
||||||
|
SearchSpecification specsSet = gson.fromJson(json, SearchSpecification.class);
|
||||||
|
|
||||||
|
response.type("application/json");
|
||||||
|
|
||||||
|
return indexClient.query(Context.fromRequest(request), specsSet);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ dependencies {
|
|||||||
implementation project(':code:libraries:term-frequency-dict')
|
implementation project(':code:libraries:term-frequency-dict')
|
||||||
|
|
||||||
implementation project(':code:api:assistant-api')
|
implementation project(':code:api:assistant-api')
|
||||||
|
implementation project(':code:api:query-api')
|
||||||
implementation project(':code:api:index-api')
|
implementation project(':code:api:index-api')
|
||||||
implementation project(':code:api:search-api')
|
implementation project(':code:api:search-api')
|
||||||
implementation project(':code:common:service-discovery')
|
implementation project(':code:common:service-discovery')
|
||||||
|
@ -2,16 +2,13 @@ package nu.marginalia.search.svc;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import nu.marginalia.index.client.IndexClient;
|
|
||||||
import nu.marginalia.index.client.model.query.SearchSpecification;
|
import nu.marginalia.index.client.model.query.SearchSpecification;
|
||||||
import nu.marginalia.index.client.model.results.DecoratedSearchResultItem;
|
import nu.marginalia.index.client.model.results.DecoratedSearchResultItem;
|
||||||
import nu.marginalia.index.client.model.results.SearchResultSet;
|
import nu.marginalia.query.client.QueryClient;
|
||||||
import nu.marginalia.search.model.PageScoreAdjustment;
|
|
||||||
import nu.marginalia.search.model.UrlDetails;
|
import nu.marginalia.search.model.UrlDetails;
|
||||||
import nu.marginalia.search.results.SearchResultDecorator;
|
import nu.marginalia.search.results.SearchResultDecorator;
|
||||||
import nu.marginalia.search.results.UrlDeduplicator;
|
import nu.marginalia.search.results.UrlDeduplicator;
|
||||||
import nu.marginalia.client.Context;
|
import nu.marginalia.client.Context;
|
||||||
import nu.marginalia.search.query.model.SearchQuery;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.slf4j.Marker;
|
import org.slf4j.Marker;
|
||||||
@ -24,17 +21,17 @@ import java.util.regex.Pattern;
|
|||||||
public class SearchQueryIndexService {
|
public class SearchQueryIndexService {
|
||||||
private final SearchResultDecorator resultDecorator;
|
private final SearchResultDecorator resultDecorator;
|
||||||
private final Comparator<UrlDetails> resultListComparator;
|
private final Comparator<UrlDetails> resultListComparator;
|
||||||
private final IndexClient indexClient;
|
private final QueryClient queryClient;
|
||||||
private final SearchQueryCountService searchVisitorCount;
|
private final SearchQueryCountService searchVisitorCount;
|
||||||
private final Marker queryMarker = MarkerFactory.getMarker("QUERY");
|
private final Marker queryMarker = MarkerFactory.getMarker("QUERY");
|
||||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SearchQueryIndexService(SearchResultDecorator resultDecorator,
|
public SearchQueryIndexService(SearchResultDecorator resultDecorator,
|
||||||
IndexClient indexClient,
|
QueryClient queryClient,
|
||||||
SearchQueryCountService searchVisitorCount) {
|
SearchQueryCountService searchVisitorCount) {
|
||||||
this.resultDecorator = resultDecorator;
|
this.resultDecorator = resultDecorator;
|
||||||
this.indexClient = indexClient;
|
this.queryClient = queryClient;
|
||||||
this.searchVisitorCount = searchVisitorCount;
|
this.searchVisitorCount = searchVisitorCount;
|
||||||
|
|
||||||
resultListComparator = Comparator.comparing(UrlDetails::getTermScore)
|
resultListComparator = Comparator.comparing(UrlDetails::getTermScore)
|
||||||
@ -45,7 +42,7 @@ public class SearchQueryIndexService {
|
|||||||
|
|
||||||
public List<UrlDetails> executeQuery(Context ctx, SearchSpecification specs) {
|
public List<UrlDetails> executeQuery(Context ctx, SearchSpecification specs) {
|
||||||
// Send the query
|
// Send the query
|
||||||
final var queryResponse = indexClient.query(ctx, specs);
|
final var queryResponse = queryClient.delegate(ctx, specs);
|
||||||
|
|
||||||
// Remove duplicates and other chaff
|
// Remove duplicates and other chaff
|
||||||
final var results = limitAndDeduplicateResults(specs, queryResponse.results);
|
final var results = limitAndDeduplicateResults(specs, queryResponse.results);
|
||||||
|
@ -46,6 +46,7 @@ include 'code:features-index:index-reverse'
|
|||||||
include 'code:features-index:domain-ranking'
|
include 'code:features-index:domain-ranking'
|
||||||
|
|
||||||
include 'code:api:search-api'
|
include 'code:api:search-api'
|
||||||
|
include 'code:api:query-api'
|
||||||
include 'code:api:index-api'
|
include 'code:api:index-api'
|
||||||
include 'code:api:assistant-api'
|
include 'code:api:assistant-api'
|
||||||
include 'code:api:process-mqapi'
|
include 'code:api:process-mqapi'
|
||||||
|
Loading…
Reference in New Issue
Block a user