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,6 +145,8 @@ async function _refresh_journal_id_background({
obj_li: [result], obj_li: [result],
log_lvl log_lvl
}); });
// IDB write is optional caching — quota failures must not discard the API result.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal', table_name: 'journal',
@@ -152,6 +154,9 @@ async function _refresh_journal_id_background({
properties_to_save, properties_to_save,
log_lvl 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,6 +338,8 @@ async function _refresh_journal_li_background({
obj_li: results, obj_li: results,
log_lvl log_lvl
}); });
// IDB write is optional caching — quota failures must not discard the API result.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal', table_name: 'journal',
@@ -340,6 +347,9 @@ async function _refresh_journal_li_background({
properties_to_save, properties_to_save,
log_lvl 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,7 +428,8 @@ 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.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal', table_name: 'journal',
@@ -426,6 +437,9 @@ export async function create_ae_obj__journal({
properties_to_save: properties_to_save, properties_to_save: properties_to_save,
log_lvl: log_lvl 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,7 +545,8 @@ 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.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal', table_name: 'journal',
@@ -539,6 +554,9 @@ export async function update_ae_obj__journal({
properties_to_save: properties_to_save, properties_to_save: properties_to_save,
log_lvl: log_lvl 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,7 +46,9 @@ 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.
// IDB write is optional caching — quota failures must not discard the API result.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal_entry', table_name: 'journal_entry',
@@ -54,6 +56,9 @@ export async function load_ae_obj_id__journal_entry({
properties_to_save: properties_to_save, properties_to_save: properties_to_save,
log_lvl: log_lvl 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,10 +158,12 @@ 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...');
} }
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal_entry', table_name: 'journal_entry',
@@ -167,6 +174,9 @@ export async function load_ae_obj_li__journal_entry({
if (log_lvl) { if (log_lvl) {
console.log('DB save completed.'); 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;
} else { } else {
@@ -237,7 +247,8 @@ 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.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal_entry', table_name: 'journal_entry',
@@ -245,6 +256,9 @@ export async function create_ae_obj__journal_entry({
properties_to_save: properties_to_save, properties_to_save: properties_to_save,
log_lvl: log_lvl 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,6 +471,8 @@ export async function qry__journal_entry({
journal_id, journal_id,
log_lvl log_lvl
}); });
// IDB write is optional caching — quota failures must not discard the API result.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal_entry', table_name: 'journal_entry',
@@ -464,6 +480,9 @@ export async function qry__journal_entry({
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 valid_result_li; return valid_result_li;
} else { } else {
@@ -588,7 +607,8 @@ 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.
try {
await db_save_ae_obj_li__ae_obj({ await db_save_ae_obj_li__ae_obj({
db_instance: db_journals, db_instance: db_journals,
table_name: 'journal_entry', table_name: 'journal_entry',
@@ -596,6 +616,9 @@ export async function update_ae_obj__journal_entry({
properties_to_save: properties_to_save, properties_to_save: properties_to_save,
log_lvl: log_lvl 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',