fix(journals): decouple IDB cache writes from API data return

QuotaExceededError on db_save was propagating through .then() into the
outer .catch(), which returned undefined and discarded the successfully-
fetched API data. Wrapped all db_save calls in try/catch so IDB failures
log a warning but never kill the load/create/update return value.

Also removed content_md_html and history_md_html from properties_to_save
— these are computed from content/history on every background refresh via
marked.parse(), so storing the rendered HTML alongside the source was
doubling storage cost per entry and the primary cause of quota exhaustion.

Affects: load, list, create, update, and qry functions in both journal
and journal_entry modules.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott Idem
2026-05-14 12:43:18 -04:00
parent b3ce65f7f6
commit a5f2ae3835
2 changed files with 114 additions and 73 deletions

View File

@@ -145,13 +145,18 @@ async function _refresh_journal_id_background({
obj_li: [result], obj_li: [result],
log_lvl log_lvl
}); });
await db_save_ae_obj_li__ae_obj({ // IDB write is optional caching — quota failures must not discard the API result.
db_instance: db_journals, try {
table_name: 'journal', await db_save_ae_obj_li__ae_obj({
obj_li: processed, db_instance: db_journals,
properties_to_save, table_name: 'journal',
log_lvl obj_li: processed,
}); properties_to_save,
log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal (quota?):', save_error);
}
// Yield to microtask queue so Dexie liveQuery observers fire before we return // Yield to microtask queue so Dexie liveQuery observers fire before we return
await Promise.resolve(); await Promise.resolve();
} }
@@ -333,13 +338,18 @@ async function _refresh_journal_li_background({
obj_li: results, obj_li: results,
log_lvl log_lvl
}); });
await db_save_ae_obj_li__ae_obj({ // IDB write is optional caching — quota failures must not discard the API result.
db_instance: db_journals, try {
table_name: 'journal', await db_save_ae_obj_li__ae_obj({
obj_li: processed, db_instance: db_journals,
properties_to_save, table_name: 'journal',
log_lvl obj_li: processed,
}); properties_to_save,
log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal (quota?):', save_error);
}
// Yield to microtask queue so Dexie liveQuery observers fire before we return // Yield to microtask queue so Dexie liveQuery observers fire before we return
await Promise.resolve(); await Promise.resolve();
} }
@@ -418,14 +428,18 @@ export async function create_ae_obj__journal({
if (log_lvl) { if (log_lvl) {
console.log('Processed object list:', processed_obj_li); console.log('Processed object list:', processed_obj_li);
} }
// Save the updated results list to the database // IDB write is optional caching — quota failures must not discard the API result.
await db_save_ae_obj_li__ae_obj({ try {
db_instance: db_journals, await db_save_ae_obj_li__ae_obj({
table_name: 'journal', db_instance: db_journals,
obj_li: processed_obj_li, table_name: 'journal',
properties_to_save: properties_to_save, obj_li: processed_obj_li,
log_lvl: log_lvl properties_to_save: properties_to_save,
}); log_lvl: log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal (quota?):', save_error);
}
} }
return journal_obj_create_result; return journal_obj_create_result;
} else { } else {
@@ -531,14 +545,18 @@ export async function update_ae_obj__journal({
if (log_lvl) { if (log_lvl) {
console.log('Processed object list:', processed_obj_li); console.log('Processed object list:', processed_obj_li);
} }
// Save the updated results list to the database // IDB write is optional caching — quota failures must not discard the API result.
await db_save_ae_obj_li__ae_obj({ try {
db_instance: db_journals, await db_save_ae_obj_li__ae_obj({
table_name: 'journal', db_instance: db_journals,
obj_li: processed_obj_li, table_name: 'journal',
properties_to_save: properties_to_save, obj_li: processed_obj_li,
log_lvl: log_lvl properties_to_save: properties_to_save,
}); log_lvl: log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal (quota?):', save_error);
}
} }
return result; return result;
} else { } else {

View File

@@ -46,14 +46,19 @@ export async function load_ae_obj_id__journal_entry({
if (log_lvl) { if (log_lvl) {
console.log('Processed object list:', processed_obj_li); console.log('Processed object list:', processed_obj_li);
} }
// Save the updated results list to the database // Save the updated results list to the database.
await db_save_ae_obj_li__ae_obj({ // IDB write is optional caching — quota failures must not discard the API result.
db_instance: db_journals, try {
table_name: 'journal_entry', await db_save_ae_obj_li__ae_obj({
obj_li: processed_obj_li, db_instance: db_journals,
properties_to_save: properties_to_save, table_name: 'journal_entry',
log_lvl: log_lvl obj_li: processed_obj_li,
}); properties_to_save: properties_to_save,
log_lvl: log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
}
} }
return journal_entry_obj_get_result; return journal_entry_obj_get_result;
} else { } else {
@@ -153,19 +158,24 @@ export async function load_ae_obj_li__journal_entry({
if (log_lvl) { if (log_lvl) {
console.log('Processed object list:', processed_obj_li); console.log('Processed object list:', processed_obj_li);
} }
// Save the updated results list to the database // Save the updated results list to the database.
// IDB write is optional caching — quota failures must not discard the API result.
if (log_lvl) { if (log_lvl) {
console.log('Saving to DB...'); console.log('Saving to DB...');
} }
await db_save_ae_obj_li__ae_obj({ try {
db_instance: db_journals, await db_save_ae_obj_li__ae_obj({
table_name: 'journal_entry', db_instance: db_journals,
obj_li: processed_obj_li, table_name: 'journal_entry',
properties_to_save: properties_to_save, obj_li: processed_obj_li,
log_lvl: log_lvl properties_to_save: properties_to_save,
}); log_lvl: log_lvl
if (log_lvl) { });
console.log('DB save completed.'); if (log_lvl) {
console.log('DB save completed.');
}
} catch (save_error) {
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
} }
} }
return journal_entry_obj_li_get_result; return journal_entry_obj_li_get_result;
@@ -237,14 +247,18 @@ export async function create_ae_obj__journal_entry({
if (log_lvl) { if (log_lvl) {
console.log('Processed object list:', processed_obj_li); console.log('Processed object list:', processed_obj_li);
} }
// Save the updated results list to the database // IDB write is optional caching — quota failures must not discard the API result.
await db_save_ae_obj_li__ae_obj({ try {
db_instance: db_journals, await db_save_ae_obj_li__ae_obj({
table_name: 'journal_entry', db_instance: db_journals,
obj_li: processed_obj_li, table_name: 'journal_entry',
properties_to_save: properties_to_save, obj_li: processed_obj_li,
log_lvl: log_lvl properties_to_save: properties_to_save,
}); log_lvl: log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
}
} }
return journal_entry_obj_create_result; return journal_entry_obj_create_result;
} else { } else {
@@ -457,13 +471,18 @@ export async function qry__journal_entry({
journal_id, journal_id,
log_lvl log_lvl
}); });
await db_save_ae_obj_li__ae_obj({ // IDB write is optional caching — quota failures must not discard the API result.
db_instance: db_journals, try {
table_name: 'journal_entry', await db_save_ae_obj_li__ae_obj({
obj_li: processed_obj_li, db_instance: db_journals,
properties_to_save, table_name: 'journal_entry',
log_lvl obj_li: processed_obj_li,
}); properties_to_save,
log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
}
} }
return valid_result_li; return valid_result_li;
} else { } else {
@@ -588,14 +607,18 @@ export async function update_ae_obj__journal_entry({
if (log_lvl) { if (log_lvl) {
console.log('Processed object list:', processed_obj_li); console.log('Processed object list:', processed_obj_li);
} }
// Save the updated results list to the database // IDB write is optional caching — quota failures must not discard the API result.
await db_save_ae_obj_li__ae_obj({ try {
db_instance: db_journals, await db_save_ae_obj_li__ae_obj({
table_name: 'journal_entry', db_instance: db_journals,
obj_li: processed_obj_li, table_name: 'journal_entry',
properties_to_save: properties_to_save, obj_li: processed_obj_li,
log_lvl: log_lvl properties_to_save: properties_to_save,
}); log_lvl: log_lvl
});
} catch (save_error) {
console.warn('IDB cache write failed for journal_entry (quota?):', save_error);
}
} }
return result; return result;
} else { } else {
@@ -848,13 +871,13 @@ const properties_to_save = [
// 'description', // 'description',
'content', 'content',
'content_md_html', // content_md_html is computed from content on every load — not stored to save IDB quota
'content_html', 'content_html',
'content_json', 'content_json',
'content_encrypted', 'content_encrypted',
'history', 'history',
'history_md_html', // history_md_html is computed from history on every load — not stored to save IDB quota
'history_encrypted', 'history_encrypted',
'passcode_hash', 'passcode_hash',