mirror of
https://github.com/MarginaliaSearch/MarginaliaSearch.git
synced 2025-02-24 13:19:02 +00:00
108 lines
4.2 KiB
Java
108 lines
4.2 KiB
Java
package nu.marginalia.search;
|
|
|
|
import com.google.inject.Inject;
|
|
import io.jooby.Context;
|
|
import io.jooby.Jooby;
|
|
import io.jooby.StatusCode;
|
|
import io.prometheus.client.Counter;
|
|
import io.prometheus.client.Histogram;
|
|
import nu.marginalia.WebsiteUrl;
|
|
import nu.marginalia.search.svc.*;
|
|
import nu.marginalia.service.discovery.property.ServicePartition;
|
|
import nu.marginalia.service.server.BaseServiceParams;
|
|
import nu.marginalia.service.server.JoobyService;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import java.util.List;
|
|
|
|
public class SearchService extends JoobyService {
|
|
|
|
private final WebsiteUrl websiteUrl;
|
|
private final SearchSiteSubscriptionService siteSubscriptionService;
|
|
|
|
private static final Logger logger = LoggerFactory.getLogger(SearchService.class);
|
|
private static final Histogram wmsa_search_service_request_time = Histogram.build()
|
|
.name("wmsa_search_service_request_time")
|
|
.linearBuckets(0.05, 0.05, 15)
|
|
.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();
|
|
|
|
@Inject
|
|
public SearchService(BaseServiceParams params,
|
|
WebsiteUrl websiteUrl,
|
|
SearchFrontPageService frontPageService,
|
|
SearchAddToCrawlQueueService addToCrawlQueueService,
|
|
SearchSiteSubscriptionService siteSubscriptionService,
|
|
SearchSiteInfoService siteInfoService,
|
|
SearchCrosstalkService crosstalkService,
|
|
SearchBrowseService searchBrowseService,
|
|
SearchQueryService searchQueryService)
|
|
throws Exception {
|
|
super(params,
|
|
ServicePartition.any(),
|
|
List.of(), // No GRPC services
|
|
List.of(new SearchFrontPageService_(frontPageService),
|
|
new SearchQueryService_(searchQueryService),
|
|
new SearchSiteInfoService_(siteInfoService),
|
|
new SearchCrosstalkService_(crosstalkService),
|
|
new SearchAddToCrawlQueueService_(addToCrawlQueueService),
|
|
new SearchBrowseService_(searchBrowseService)
|
|
));
|
|
this.websiteUrl = websiteUrl;
|
|
|
|
this.siteSubscriptionService = siteSubscriptionService;
|
|
}
|
|
|
|
@Override
|
|
public void startJooby(Jooby jooby) {
|
|
super.startJooby(jooby);
|
|
|
|
final String startTimeAttribute = "start-time";
|
|
|
|
jooby.get("/export-opml", siteSubscriptionService::exportOpml);
|
|
|
|
jooby.get("/site/https://*", this::handleSiteUrlRedirect);
|
|
jooby.get("/site/http://*", this::handleSiteUrlRedirect);
|
|
|
|
jooby.before((Context ctx) -> {
|
|
ctx.setAttribute(startTimeAttribute, System.nanoTime());
|
|
});
|
|
|
|
jooby.after((Context ctx, Object result, Throwable failure) -> {
|
|
if (failure != null) {
|
|
wmsa_search_service_error_count.labels(ctx.getRoute().getPattern(), ctx.getMethod()).inc();
|
|
}
|
|
else {
|
|
Long startTime = ctx.getAttribute(startTimeAttribute);
|
|
if (startTime != null) {
|
|
wmsa_search_service_request_time.labels(ctx.getRoute().getPattern(), ctx.getMethod())
|
|
.observe((System.nanoTime() - startTime) / 1e9);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
/** Redirect handler for the case when the user passes
|
|
* an url like /site/https://example.com/, in this
|
|
* scenario we want to extract the domain name and redirect
|
|
* to /site/example.com/
|
|
*/
|
|
private Context handleSiteUrlRedirect(Context ctx) {
|
|
var pv = ctx.path("*").value();
|
|
int trailSlash = pv.indexOf('/');
|
|
if (trailSlash > 0) {
|
|
pv = pv.substring(0, trailSlash);
|
|
}
|
|
ctx.sendRedirect(StatusCode.TEMPORARY_REDIRECT, websiteUrl.withPath("site/" + pv));
|
|
return ctx;
|
|
}
|
|
|
|
}
|