Skip to content

Commit

Permalink
Merge pull request #9539 from cdrini/9535/fix/long-list-edit
Browse files Browse the repository at this point in the history
Chunk keys in lazy-thing-preview; fix long lists editing
  • Loading branch information
cdrini authored Jul 12, 2024
2 parents 745e6ec + 106e9b9 commit 18c2463
Showing 1 changed file with 36 additions and 32 deletions.
68 changes: 36 additions & 32 deletions openlibrary/plugins/openlibrary/js/lazy-thing-preview.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// @ts-check
import debounce from 'lodash/debounce';
import chunk from 'lodash/chunk';

/**
* Responds to HTML like:
Expand Down Expand Up @@ -60,75 +61,78 @@ export class LazyThingPreview {

/**
* @param {string[]} keys
* @returns {Promise<object[]>}
* @returns {AsyncGenerator<object[]>}
*/
async getThings(keys) {
async* getThings(keys) {
const workKeys = keys.filter(key => key.startsWith('/works/'));
const editionKeys = keys.filter(key => key.startsWith('/books/'));
const authorKeys = keys.filter(key => key.startsWith('/authors/'));
const fields = 'key,type,cover_i,first_publish_year,author_name,title,subtitle,edition_count,editions';
let docs = [];
if (workKeys.length) {
for (const keys of chunk(workKeys, 100)) {
const resp = await fetch(`/search.json?${new URLSearchParams({
q: `key:(${workKeys.join(' OR ')})`,
q: `key:(${keys.join(' OR ')})`,
fields,
limit: '100',
})}`).then(r => r.json());
docs = docs.concat(resp.docs);
yield resp.docs;
}
if (editionKeys.length) {
for (const keys of chunk(editionKeys, 100)) {
const resp = await fetch(`/search.json?${new URLSearchParams({
q: `edition_key:(${editionKeys
q: `edition_key:(${keys
.map(key => key.split('/').pop())
.join(' OR ')})`,
fields,
limit: '100',
})}`).then(r => r.json());
docs = docs.concat(resp.docs);
yield resp.docs;
}
if (authorKeys.length) {
for (const keys of chunk(authorKeys, 100)) {
const resp = await fetch(`/search/authors.json?${new URLSearchParams({
q: `key:(${authorKeys.join(' OR ')})`,
q: `key:(${keys.join(' OR ')})`,
fields: 'key,type,name,top_work,top_subjects,birth_date,death_date',
limit: '100',
})}`).then(r => r.json());
for (const doc of resp.docs) {
// This API returns keys without the /authors/ prefix 😭
doc.key = `/authors/${doc.key}`;
}
docs = docs.concat(resp.docs);
yield resp.docs;
}

return docs;
}

async render() {
const keys = this.queue.map(({key}) => key);
const things = await this.getThings(keys);
for (const thing of things) {
this.cache[thing.key] = thing;
if (thing.type === 'work') {
const book = thing;
book.full_title = book.subtitle ? `${book.title}: ${book.subtitle}` : book.title;
if (book.editions.docs.length) {
const ed = book.editions.docs[0];
ed.full_title = ed.subtitle ? `${ed.title}: ${ed.subtitle}` : ed.title;
ed.author_name = book.author_name;
ed.edition_count = book.edition_count;
this.cache[ed.key] = ed;
const render_fn_map = Object.fromEntries(
this.queue.map(({key, render_fn}) => [key, render_fn])
);
for await (const thingBatch of this.getThings(keys)) {
for (const thing of thingBatch) {
this.cache[thing.key] = thing;
if (thing.type === 'work') {
const book = thing;
book.full_title = book.subtitle ? `${book.title}: ${book.subtitle}` : book.title;
if (book.editions.docs.length) {
const ed = book.editions.docs[0];
ed.full_title = ed.subtitle ? `${ed.title}: ${ed.subtitle}` : ed.title;
ed.author_name = book.author_name;
ed.edition_count = book.edition_count;
this.cache[ed.key] = ed;

if (ed.key in render_fn_map) {
this.renderKey(ed.key, render_fn_map[ed.key], ed);
}
}
}

if (thing.key in render_fn_map) {
this.renderKey(thing.key, render_fn_map[thing.key], thing);
}
}
}

const missingKeys = keys.filter(key => !this.cache[key]);
// eslint-disable-next-line no-console
console.warn('Books missing from cache', missingKeys);

for (const {key, render_fn} of this.queue) {
if (this.cache[key]) {
this.renderKey(key, render_fn, this.cache[key]);
}
}
this.queue = [];
}
}

0 comments on commit 18c2463

Please sign in to comment.