1
1
mirror of https://github.com/MarginaliaSearch/MarginaliaSearch.git synced 2025-10-06 17:32:39 +02:00

Compare commits

...

5 Commits

Author SHA1 Message Date
Viktor Lofgren
79da622e3b (search) Update front page with new banner about move 2025-01-08 21:38:19 +01:00
Viktor Lofgren
3da8337ba6 (feeds) Add system property for exporting fetched feeds to a slop table for debugging 2025-01-08 20:49:16 +01:00
Viktor Lofgren
a32d230f0a (special) Trigger deployment 2025-01-08 20:07:54 +01:00
Viktor Lofgren
3772bfd387 (query) Fix handling of optional ranking parameters 2025-01-08 17:11:22 +01:00
Viktor Lofgren
02a7900d1a (search) Correct search-in-title toggle in search UI 2025-01-08 16:51:10 +01:00
9 changed files with 106 additions and 19 deletions

View File

@@ -29,6 +29,7 @@ dependencies {
implementation libs.jsoup implementation libs.jsoup
implementation project(':third-party:rssreader') implementation project(':third-party:rssreader')
implementation libs.opencsv implementation libs.opencsv
implementation libs.slop
implementation libs.sqlite implementation libs.sqlite
implementation libs.bundles.slf4j implementation libs.bundles.slf4j
implementation libs.commons.lang3 implementation libs.commons.lang3

View File

@@ -96,6 +96,7 @@ public class FeedFetcherService {
throw new IllegalStateException("Already updating feeds, refusing to start another update"); throw new IllegalStateException("Already updating feeds, refusing to start another update");
} }
try (FeedDbWriter writer = feedDb.createWriter(); try (FeedDbWriter writer = feedDb.createWriter();
HttpClient client = HttpClient.newBuilder() HttpClient client = HttpClient.newBuilder()
.connectTimeout(Duration.ofSeconds(15)) .connectTimeout(Duration.ofSeconds(15))
@@ -103,6 +104,7 @@ public class FeedFetcherService {
.followRedirects(HttpClient.Redirect.NORMAL) .followRedirects(HttpClient.Redirect.NORMAL)
.version(HttpClient.Version.HTTP_2) .version(HttpClient.Version.HTTP_2)
.build(); .build();
FeedJournal feedJournal = FeedJournal.create();
var heartbeat = serviceHeartbeat.createServiceAdHocTaskHeartbeat("Update Rss Feeds") var heartbeat = serviceHeartbeat.createServiceAdHocTaskHeartbeat("Update Rss Feeds")
) { ) {
updating = true; updating = true;
@@ -155,6 +157,8 @@ public class FeedFetcherService {
case FetchResult.Success(String value, String etag) -> { case FetchResult.Success(String value, String etag) -> {
writer.saveEtag(feed.domain(), etag); writer.saveEtag(feed.domain(), etag);
writer.saveFeed(parseFeed(value, feed)); writer.saveFeed(parseFeed(value, feed));
feedJournal.record(feed.feedUrl(), value);
} }
case FetchResult.NotModified() -> { case FetchResult.NotModified() -> {
writer.saveEtag(feed.domain(), ifNoneMatchTag); writer.saveEtag(feed.domain(), ifNoneMatchTag);

View File

@@ -0,0 +1,64 @@
package nu.marginalia.rss.svc;
import nu.marginalia.WmsaHome;
import nu.marginalia.slop.SlopTable;
import nu.marginalia.slop.column.string.StringColumn;
import nu.marginalia.slop.desc.StorageType;
import org.apache.commons.io.FileUtils;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
/** Utility for recording fetched feeds to a journal, useful in debugging feed parser issues.
*/
public interface FeedJournal extends AutoCloseable {
StringColumn urlColumn = new StringColumn("url");
StringColumn contentsColumn = new StringColumn("contents", StandardCharsets.UTF_8, StorageType.ZSTD);
void record(String url, String contents) throws IOException;
void close() throws IOException;
static FeedJournal create() throws IOException {
if (Boolean.getBoolean("feedFetcher.persistJournal")) {
Path journalPath = WmsaHome.getDataPath().resolve("feed-journal");
if (Files.isDirectory(journalPath)) {
FileUtils.deleteDirectory(journalPath.toFile());
}
Files.createDirectories(journalPath);
return new RecordingFeedJournal(journalPath);
}
else {
return new NoOpFeedJournal();
}
}
class NoOpFeedJournal implements FeedJournal {
@Override
public void record(String url, String contents) {}
@Override
public void close() {}
}
class RecordingFeedJournal extends SlopTable implements FeedJournal {
private final StringColumn.Writer urlWriter;
private final StringColumn.Writer contentsWriter;
public RecordingFeedJournal(Path path) throws IOException {
super(path, SlopTable.getNumPages(path, FeedJournal.urlColumn));
urlWriter = urlColumn.create(this);
contentsWriter = contentsColumn.create(this);
}
public synchronized void record(String url, String contents) throws IOException {
urlWriter.put(url);
contentsWriter.put(contents);
}
}
}

View File

@@ -15,7 +15,10 @@ import nu.marginalia.api.searchquery.model.results.debug.ResultRankingDetails;
import nu.marginalia.index.query.limit.QueryStrategy; import nu.marginalia.index.query.limit.QueryStrategy;
import nu.marginalia.model.EdgeUrl; import nu.marginalia.model.EdgeUrl;
import java.util.*; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class QueryProtobufCodec { public class QueryProtobufCodec {
@@ -42,13 +45,27 @@ public class QueryProtobufCodec {
else else
builder.setQueryStrategy(request.getQueryStrategy()); builder.setQueryStrategy(request.getQueryStrategy());
if (query.specs.rankingParams != null && request.getTemporalBias().getBias() != RpcTemporalBias.Bias.NONE) { if (request.getTemporalBias().getBias() != RpcTemporalBias.Bias.NONE) {
if (query.specs.rankingParams != null) {
builder.setParameters( builder.setParameters(
RpcResultRankingParameters.newBuilder(query.specs.rankingParams) RpcResultRankingParameters.newBuilder(query.specs.rankingParams)
.setTemporalBias(request.getTemporalBias()) .setTemporalBias(request.getTemporalBias())
.build() .build()
); );
} else {
builder.setParameters(
RpcResultRankingParameters.newBuilder(PrototypeRankingParameters.sensibleDefaults())
.setTemporalBias(request.getTemporalBias())
.build()
);
} }
} else if (query.specs.rankingParams != null) {
builder.setParameters(query.specs.rankingParams);
}
// else {
// if we have no ranking params, we don't need to set them, the client check and use the default values
// so we don't need to send this huge object over the wire
// }
return builder.build(); return builder.build();
} }
@@ -292,7 +309,7 @@ public class QueryProtobufCodec {
IndexProtobufCodec.convertSpecLimit(specs.getRank()), IndexProtobufCodec.convertSpecLimit(specs.getRank()),
specs.getQueryLimits(), specs.getQueryLimits(),
QueryStrategy.valueOf(specs.getQueryStrategy()), QueryStrategy.valueOf(specs.getQueryStrategy()),
Objects.requireNonNullElseGet(specs.getParameters(), PrototypeRankingParameters::sensibleDefaults) specs.hasParameters() ? specs.getParameters() : null
); );
} }

View File

@@ -5,6 +5,7 @@ import nu.marginalia.api.searchquery.RpcResultRankingParameters;
import nu.marginalia.index.query.limit.QueryStrategy; import nu.marginalia.index.query.limit.QueryStrategy;
import nu.marginalia.index.query.limit.SpecificationLimit; import nu.marginalia.index.query.limit.SpecificationLimit;
import javax.annotation.Nullable;
import java.util.List; import java.util.List;
public class SearchSpecification { public class SearchSpecification {
@@ -28,6 +29,7 @@ public class SearchSpecification {
public final QueryStrategy queryStrategy; public final QueryStrategy queryStrategy;
@Nullable
public final RpcResultRankingParameters rankingParams; public final RpcResultRankingParameters rankingParams;
public SearchSpecification(SearchQuery query, public SearchSpecification(SearchQuery query,
@@ -40,7 +42,7 @@ public class SearchSpecification {
SpecificationLimit rank, SpecificationLimit rank,
RpcQueryLimits queryLimits, RpcQueryLimits queryLimits,
QueryStrategy queryStrategy, QueryStrategy queryStrategy,
RpcResultRankingParameters rankingParams) @Nullable RpcResultRankingParameters rankingParams)
{ {
this.query = query; this.query = query;
this.domains = domains; this.domains = domains;

View File

@@ -13,8 +13,6 @@ import nu.marginalia.index.query.IndexSearchBudget;
import nu.marginalia.index.query.limit.QueryStrategy; import nu.marginalia.index.query.limit.QueryStrategy;
import nu.marginalia.index.searchset.SearchSet; import nu.marginalia.index.searchset.SearchSet;
import java.util.Objects;
import static nu.marginalia.api.searchquery.IndexProtobufCodec.convertSpecLimit; import static nu.marginalia.api.searchquery.IndexProtobufCodec.convertSpecLimit;
public class SearchParameters { public class SearchParameters {
@@ -88,7 +86,7 @@ public class SearchParameters {
compiledQuery = CompiledQueryParser.parse(this.query.compiledQuery); compiledQuery = CompiledQueryParser.parse(this.query.compiledQuery);
compiledQueryIds = compiledQuery.mapToLong(SearchTermsUtil::getWordId); compiledQueryIds = compiledQuery.mapToLong(SearchTermsUtil::getWordId);
rankingParams = Objects.requireNonNullElseGet(request.getParameters(), PrototypeRankingParameters::sensibleDefaults); rankingParams = request.hasParameters() ? request.getParameters() : PrototypeRankingParameters.sensibleDefaults();
} }

View File

@@ -37,7 +37,7 @@ public class SearchQueryService {
@QueryParam String profile, @QueryParam String profile,
@QueryParam String js, @QueryParam String js,
@QueryParam String recent, @QueryParam String recent,
@QueryParam String title, @QueryParam String searchTitle,
@QueryParam String adtech, @QueryParam String adtech,
@QueryParam Integer page @QueryParam Integer page
) { ) {
@@ -47,7 +47,7 @@ public class SearchQueryService {
SearchProfile.getSearchProfile(profile), SearchProfile.getSearchProfile(profile),
SearchJsParameter.parse(js), SearchJsParameter.parse(js),
SearchRecentParameter.parse(recent), SearchRecentParameter.parse(recent),
SearchTitleParameter.parse(title), SearchTitleParameter.parse(searchTitle),
SearchAdtechParameter.parse(adtech), SearchAdtechParameter.parse(adtech),
false, false,
Objects.requireNonNullElse(page,1)); Objects.requireNonNullElse(page,1));

View File

@@ -34,12 +34,12 @@
<div class="max-w-7xl mx-auto flex flex-col space-y-4 fill-w"> <div class="max-w-7xl mx-auto flex flex-col space-y-4 fill-w">
<div class="border dark:border-gray-600 dark:bg-gray-800 bg-white rounded p-2 m-4 "> <div class="border dark:border-gray-600 dark:bg-gray-800 bg-white rounded p-2 m-4 ">
<div class="text-slate-700 dark:text-white text-sm p-4"> <div class="text-slate-700 dark:text-white text-sm p-4">
<div class="fas fa-wrench mr-1 text-margeblue dark:text-slate-200"></div> <div class="fas fa-gift mr-1 text-margeblue dark:text-slate-200"></div>
This is the new design and home of Marginalia Search. Migration to the new domain <pre class="inline text-red-800 dark:text-red-100">marginalia-search.com</pre> is currently <em>in progress</em>, This is the new design and home of Marginalia Search.
so mind that some things may be a bit broken for a day or two. <a href="https://about.marginalia-search.com/article/redesign/" class="underline text-liteblue dark:text-blue-200">Read more</a>. You can about what this entails <a href="https://about.marginalia-search.com/article/redesign/" class="underline text-liteblue dark:text-blue-200">here</a>.
<p class="my-4"></p> <p class="my-4"></p>
If you have any issues or feedback regarding this change, please email The old version of Marginalia Search remains available at
<a href="mailto:contact@marginalia-search.com" class="underline text-liteblue dark:text-blue-200">contact@marginalia-search.com</a>. <a href="https://old-search.marginalia.nu/" class="underline text-liteblue dark:text-blue-200">https://old-search.marginalia.nu/</a>.
</div> </div>
</div> </div>
<div class="mx-auto flex flex-col sm:flex-row my-4 sm:space-x-2 space-y-2 sm:space-y-0 w-full md:w-auto px-2"> <div class="mx-auto flex flex-col sm:flex-row my-4 sm:space-x-2 space-y-2 sm:space-y-0 w-full md:w-auto px-2">

View File

@@ -1,3 +1,4 @@
## This is a token file for automatic deployment ## This is a token file for automatic deployment
2025-01-08: Deploy executor.
2025-01-07: Deploy executor. 2025-01-07: Deploy executor.