2023-03-04 12:19:01 +00:00
|
|
|
package nu.marginalia.search;
|
2022-05-19 15:45:26 +00:00
|
|
|
|
|
|
|
import com.google.inject.Inject;
|
2024-01-02 14:02:29 +00:00
|
|
|
import io.prometheus.client.Counter;
|
|
|
|
import io.prometheus.client.Histogram;
|
2023-03-04 12:19:01 +00:00
|
|
|
import nu.marginalia.WebsiteUrl;
|
|
|
|
import nu.marginalia.search.svc.*;
|
2024-12-10 18:13:13 +00:00
|
|
|
import nu.marginalia.service.discovery.property.ServicePartition;
|
2024-11-11 20:14:38 +00:00
|
|
|
import nu.marginalia.service.server.BaseServiceParams;
|
2024-12-10 18:13:13 +00:00
|
|
|
import nu.marginalia.service.server.JoobyService;
|
2024-11-11 20:14:38 +00:00
|
|
|
import nu.marginalia.service.server.StaticResources;
|
2022-05-19 15:45:26 +00:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
2024-12-10 18:13:13 +00:00
|
|
|
import java.util.List;
|
2022-05-19 15:45:26 +00:00
|
|
|
|
2024-12-10 18:13:13 +00:00
|
|
|
public class SearchService extends JoobyService {
|
2022-05-19 15:45:26 +00:00
|
|
|
|
2022-06-09 19:47:59 +00:00
|
|
|
private final WebsiteUrl websiteUrl;
|
2023-03-16 20:35:54 +00:00
|
|
|
private final StaticResources staticResources;
|
2022-08-23 22:41:17 +00:00
|
|
|
|
2023-03-04 12:19:01 +00:00
|
|
|
private static final Logger logger = LoggerFactory.getLogger(SearchService.class);
|
2024-01-02 14:02:29 +00:00
|
|
|
private static final Histogram wmsa_search_service_request_time = Histogram.build()
|
|
|
|
.name("wmsa_search_service_request_time")
|
2024-01-02 16:13:14 +00:00
|
|
|
.linearBuckets(0.05, 0.05, 15)
|
2024-01-02 14:02:29 +00:00
|
|
|
.labelNames("matchedPath", "method")
|
|
|
|
.help("Search service request time (seconds)")
|
|
|
|
.register();
|
|
|
|
private static final Counter wmsa_search_service_error_count = Counter.build()
|
|
|
|
.name("wmsa_search_service_error_count")
|
|
|
|
.labelNames("matchedPath", "method")
|
|
|
|
.help("Search service error count")
|
|
|
|
.register();
|
2022-05-19 15:45:26 +00:00
|
|
|
|
|
|
|
@Inject
|
2023-07-03 08:40:32 +00:00
|
|
|
public SearchService(BaseServiceParams params,
|
2023-03-04 12:19:01 +00:00
|
|
|
WebsiteUrl websiteUrl,
|
|
|
|
StaticResources staticResources,
|
2023-03-19 11:54:58 +00:00
|
|
|
SearchFrontPageService frontPageService,
|
2023-03-04 12:19:01 +00:00
|
|
|
SearchAddToCrawlQueueService addToCrawlQueueService,
|
2023-11-18 16:42:35 +00:00
|
|
|
SearchSiteInfoService siteInfoService,
|
2023-12-17 16:50:44 +00:00
|
|
|
SearchCrosstalkService crosstalkService,
|
2024-12-05 13:00:17 +00:00
|
|
|
SearchBrowseService searchBrowseService,
|
2024-11-11 20:14:38 +00:00
|
|
|
SearchQueryService searchQueryService)
|
2024-12-10 18:13:13 +00:00
|
|
|
throws Exception {
|
|
|
|
super(params,
|
|
|
|
ServicePartition.any(),
|
|
|
|
List.of(),
|
|
|
|
List.of(new SearchFrontPageService_(frontPageService),
|
|
|
|
new SearchQueryService_(searchQueryService),
|
|
|
|
new SearchSiteInfoService_(siteInfoService),
|
|
|
|
new SearchCrosstalkService_(crosstalkService),
|
|
|
|
new SearchAddToCrawlQueueService_(addToCrawlQueueService),
|
|
|
|
new SearchBrowseService_(searchBrowseService)
|
|
|
|
));
|
2022-05-19 15:45:26 +00:00
|
|
|
|
2022-06-09 19:47:59 +00:00
|
|
|
this.websiteUrl = websiteUrl;
|
2022-08-23 22:41:17 +00:00
|
|
|
this.staticResources = staticResources;
|
2022-05-19 15:45:26 +00:00
|
|
|
|
|
|
|
}
|
2024-12-10 18:13:13 +00:00
|
|
|
//
|
|
|
|
// SearchServiceMetrics.get("/search", searchQueryService::pathSearch);
|
|
|
|
// SearchServiceMetrics.get("/", frontPageService::render);
|
|
|
|
// SearchServiceMetrics.get("/news.xml", frontPageService::renderNewsFeed);
|
|
|
|
//
|
|
|
|
// SearchServiceMetrics.post("/site/suggest/", addToCrawlQueueService::suggestCrawling);
|
|
|
|
//
|
|
|
|
// SearchServiceMetrics.get("/site-search/:site/*", this::siteSearchRedir);
|
|
|
|
//
|
|
|
|
// SearchServiceMetrics.get("/site", siteInfoService::handleOverview);
|
|
|
|
// SearchServiceMetrics.get("/site/:site", siteInfoService::handle);
|
|
|
|
// SearchServiceMetrics.post("/site/:site", siteInfoService::handlePost);
|
|
|
|
//
|
|
|
|
// SearchServiceMetrics.get("/explore", searchBrowseService::handleBrowseRandom);
|
|
|
|
// SearchServiceMetrics.get("/explore/:site", searchBrowseService::handleBrowseSite);
|
|
|
|
//
|
|
|
|
// SearchServiceMetrics.get("/crosstalk/", crosstalkService::handle);
|
|
|
|
//
|
|
|
|
// SearchServiceMetrics.get("/:resource", this::serveStatic);
|
|
|
|
// Spark.exception(Exception.class, (e,p,q) -> {
|
|
|
|
// logger.error("Error during processing", e);
|
|
|
|
// wmsa_search_service_error_count.labels(p.pathInfo(), p.requestMethod()).inc();
|
|
|
|
// errorPageService.serveError(p, q);
|
|
|
|
// });
|
|
|
|
//
|
|
|
|
// // Add compression
|
|
|
|
// Spark.after((rq, rs) -> {
|
|
|
|
// rs.header("Content-Encoding", "gzip");
|
|
|
|
// });
|
|
|
|
//
|
|
|
|
// Spark.awaitInitialization();
|
|
|
|
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// /** Wraps a route with a timer and a counter */
|
|
|
|
// private static class SearchServiceMetrics implements Route {
|
|
|
|
// private final Route delegatedRoute;
|
|
|
|
//
|
|
|
|
// static void get(String path, Route route) {
|
|
|
|
// Spark.get(path, new SearchServiceMetrics(route));
|
|
|
|
// }
|
|
|
|
// static void post(String path, Route route) {
|
|
|
|
// Spark.post(path, new SearchServiceMetrics(route));
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// private SearchServiceMetrics(Route delegatedRoute) {
|
|
|
|
// this.delegatedRoute = delegatedRoute;
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// @Override
|
|
|
|
// public Object handle(Request request, Response response) throws Exception {
|
|
|
|
// return wmsa_search_service_request_time
|
|
|
|
// .labels(request.matchedPath(), request.requestMethod())
|
|
|
|
// .time(() -> delegatedRoute.handle(request, response));
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// private Object serveStatic(Request request, Response response) {
|
|
|
|
// String resource = request.params("resource");
|
|
|
|
// staticResources.serveStatic("search", resource, request, response);
|
|
|
|
// return "";
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// private Object siteSearchRedir(Request request, Response response) {
|
|
|
|
// final String site = request.params("site");
|
|
|
|
// final String searchTerms;
|
|
|
|
//
|
|
|
|
// if (request.splat().length == 0) searchTerms = "";
|
|
|
|
// else searchTerms = request.splat()[0];
|
|
|
|
//
|
|
|
|
// final String query = URLEncoder.encode(String.format("%s site:%s", searchTerms, site), StandardCharsets.UTF_8).trim();
|
|
|
|
// final String profile = request.queryParamOrDefault("profile", "yolo");
|
|
|
|
//
|
|
|
|
// response.redirect(websiteUrl.withPath("search?query="+query+"&profile="+profile));
|
|
|
|
//
|
|
|
|
// return "";
|
|
|
|
// }
|
2022-05-19 15:45:26 +00:00
|
|
|
|
|
|
|
}
|