fixing filtering of lists (#311)

* fixing listing filtering by applying the correct id
This commit is contained in:
Christian Kellner
2026-06-02 09:24:45 +02:00
committed by GitHub
parent 573868eccb
commit a834abc31c
3 changed files with 24 additions and 18 deletions

View File

@@ -5,9 +5,10 @@
import { NoNewListingsWarning } from './errors.js'; import { NoNewListingsWarning } from './errors.js';
import { import {
storeListings,
getKnownListingHashesForJobAndProvider,
deleteListingsById, deleteListingsById,
getKnownListingHashesForJobAndProvider,
storeListings,
updateListingDistance,
} from './services/storage/listingsStorage.js'; } from './services/storage/listingsStorage.js';
import { getJob } from './services/storage/jobStorage.js'; import { getJob } from './services/storage/jobStorage.js';
import * as notify from './notification/notify.js'; import * as notify from './notification/notify.js';
@@ -16,8 +17,7 @@ import urlModifier from './services/queryStringMutator.js';
import logger from './services/logger.js'; import logger from './services/logger.js';
import { geocodeAddress } from './services/geocoding/geoCodingService.js'; import { geocodeAddress } from './services/geocoding/geoCodingService.js';
import { distanceMeters } from './services/listings/distanceCalculator.js'; import { distanceMeters } from './services/listings/distanceCalculator.js';
import { getUserSettings, getSettings } from './services/storage/settingsStorage.js'; import { getSettings, getUserSettings } from './services/storage/settingsStorage.js';
import { updateListingDistance } from './services/storage/listingsStorage.js';
import booleanPointInPolygon from '@turf/boolean-point-in-polygon'; import booleanPointInPolygon from '@turf/boolean-point-in-polygon';
import { formatListing } from './utils/formatListing.js'; import { formatListing } from './utils/formatListing.js';
@@ -97,9 +97,9 @@ class FredyPipelineExecutioner {
} }
/** /**
* Optionally enrich new listings with data from their detail pages. * Optionally, enrich new listings with data from their detail pages.
* Only called when the provider config defines a `fetchDetails` function. * Only called when the provider config defines a `fetchDetails` function.
* Runs all fetches in parallel. Each individual fetch must handle its own errors * Runs all fetches in parallel. Each fetch must handle its own errors
* and always resolve (never reject) to avoid aborting other listings. * and always resolve (never reject) to avoid aborting other listings.
* *
* @param {Listing[]} newListings New listings to enrich. * @param {Listing[]} newListings New listings to enrich.
@@ -132,7 +132,7 @@ class FredyPipelineExecutioner {
for (const listing of newListings) { for (const listing of newListings) {
if (listing.address) { if (listing.address) {
const coords = await geocodeAddress(listing.address); const coords = await geocodeAddress(listing.address);
if (coords) { if (coords && coords.lat !== -1 && coords.lng !== -1) {
listing.latitude = coords.lat; listing.latitude = coords.lat;
listing.longitude = coords.lng; listing.longitude = coords.lng;
} }
@@ -264,15 +264,15 @@ class FredyPipelineExecutioner {
const requiredKeys = this._providerConfig.requiredFieldNames; const requiredKeys = this._providerConfig.requiredFieldNames;
const requireValues = ['id', 'link', 'title']; const requireValues = ['id', 'link', 'title'];
const filteredListings = listings return (
// this should never filter some listings out, because the normalize function should always extract all fields. listings
.filter((item) => requiredKeys.every((key) => key in item)) // this should never filter some listings out, because the normalize function should always extract all fields.
// TODO: move blacklist filter to this file, so it will handle for all providers in same way. .filter((item) => requiredKeys.every((key) => key in item))
.filter(this._providerConfig.filter) // TODO: move blacklist filter to this file, so it will handle for all providers in same way.
// filter out listings that are missing required fields .filter(this._providerConfig.filter)
.filter((item) => requireValues.every((key) => item[key] != null)); // filter out listings that are missing required fields
.filter((item) => requireValues.every((key) => item[key] != null))
return filteredListings; );
} }
/** /**

View File

@@ -214,6 +214,8 @@ export const storeListings = (jobId, providerId, listings) => {
longitude: item.longitude || null, longitude: item.longitude || null,
}; };
stmt.run(params); stmt.run(params);
// Propagate the DB primary key back so downstream pipeline steps use the correct id
item.id = params.id;
} }
}); });
@@ -417,9 +419,10 @@ export const deleteListingsByJobId = (jobId, hardDelete = false) => {
}; };
/** /**
* Delete listings by a list of listing IDs. * Delete listings by a list of listing IDs (the nanoid primary key stored in the `id` column).
* Used by API routes that receive row IDs from the client.
* *
* @param {string[]} ids - Array of listing IDs to delete. * @param {string[]} ids - Array of DB row IDs to delete.
* @param {boolean} [hardDelete=false] - Whether to hard delete from DB or just mark as deleted. * @param {boolean} [hardDelete=false] - Whether to hard delete from DB or just mark as deleted.
* @returns {any} The result from SqliteConnection.execute. * @returns {any} The result from SqliteConnection.execute.
*/ */

View File

@@ -32,4 +32,7 @@ export const deletedIds = [];
export const deleteListingsById = (ids) => { export const deleteListingsById = (ids) => {
deletedIds.push(...ids); deletedIds.push(...ids);
}; };
export const deleteListingsByHash = (hashes) => {
deletedIds.push(...hashes);
};
/* eslint-enable no-unused-vars */ /* eslint-enable no-unused-vars */