From a5f2ae38358d3e00031a097a04fd8701bd42862a Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Thu, 14 May 2026 12:43:18 -0400 Subject: [PATCH] fix(journals): decouple IDB cache writes from API data return MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- src/lib/ae_journals/ae_journals__journal.ts | 78 ++++++++----- .../ae_journals/ae_journals__journal_entry.ts | 109 +++++++++++------- 2 files changed, 114 insertions(+), 73 deletions(-) diff --git a/src/lib/ae_journals/ae_journals__journal.ts b/src/lib/ae_journals/ae_journals__journal.ts index 3ac9e510..4c2dcce5 100644 --- a/src/lib/ae_journals/ae_journals__journal.ts +++ b/src/lib/ae_journals/ae_journals__journal.ts @@ -145,13 +145,18 @@ async function _refresh_journal_id_background({ obj_li: [result], log_lvl }); - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal', - obj_li: processed, - properties_to_save, - log_lvl - }); + // IDB write is optional caching — quota failures must not discard the API result. + try { + await db_save_ae_obj_li__ae_obj({ + db_instance: db_journals, + table_name: 'journal', + 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 await Promise.resolve(); } @@ -333,13 +338,18 @@ async function _refresh_journal_li_background({ obj_li: results, log_lvl }); - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal', - obj_li: processed, - properties_to_save, - log_lvl - }); + // IDB write is optional caching — quota failures must not discard the API result. + try { + await db_save_ae_obj_li__ae_obj({ + db_instance: db_journals, + table_name: 'journal', + 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 await Promise.resolve(); } @@ -418,14 +428,18 @@ export async function create_ae_obj__journal({ if (log_lvl) { console.log('Processed object list:', processed_obj_li); } - // Save the updated results list to the database - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal', - obj_li: processed_obj_li, - properties_to_save: properties_to_save, - 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({ + db_instance: db_journals, + table_name: 'journal', + 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 (quota?):', save_error); + } } return journal_obj_create_result; } else { @@ -531,14 +545,18 @@ export async function update_ae_obj__journal({ if (log_lvl) { console.log('Processed object list:', processed_obj_li); } - // Save the updated results list to the database - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal', - obj_li: processed_obj_li, - properties_to_save: properties_to_save, - 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({ + db_instance: db_journals, + table_name: 'journal', + 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 (quota?):', save_error); + } } return result; } else { diff --git a/src/lib/ae_journals/ae_journals__journal_entry.ts b/src/lib/ae_journals/ae_journals__journal_entry.ts index f83b20cd..c86d0064 100644 --- a/src/lib/ae_journals/ae_journals__journal_entry.ts +++ b/src/lib/ae_journals/ae_journals__journal_entry.ts @@ -46,14 +46,19 @@ export async function load_ae_obj_id__journal_entry({ if (log_lvl) { console.log('Processed object list:', processed_obj_li); } - // Save the updated results list to the database - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal_entry', - obj_li: processed_obj_li, - properties_to_save: properties_to_save, - log_lvl: log_lvl - }); + // 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({ + db_instance: db_journals, + table_name: 'journal_entry', + 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; } else { @@ -153,19 +158,24 @@ export async function load_ae_obj_li__journal_entry({ if (log_lvl) { 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) { console.log('Saving to DB...'); } - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal_entry', - obj_li: processed_obj_li, - properties_to_save: properties_to_save, - log_lvl: log_lvl - }); - if (log_lvl) { - console.log('DB save completed.'); + try { + await db_save_ae_obj_li__ae_obj({ + db_instance: db_journals, + table_name: 'journal_entry', + obj_li: processed_obj_li, + properties_to_save: properties_to_save, + log_lvl: log_lvl + }); + 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; @@ -237,14 +247,18 @@ export async function create_ae_obj__journal_entry({ if (log_lvl) { console.log('Processed object list:', processed_obj_li); } - // Save the updated results list to the database - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal_entry', - obj_li: processed_obj_li, - properties_to_save: properties_to_save, - 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({ + db_instance: db_journals, + table_name: 'journal_entry', + 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_create_result; } else { @@ -457,13 +471,18 @@ export async function qry__journal_entry({ journal_id, log_lvl }); - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal_entry', - obj_li: processed_obj_li, - properties_to_save, - log_lvl - }); + // IDB write is optional caching — quota failures must not discard the API result. + try { + await db_save_ae_obj_li__ae_obj({ + db_instance: db_journals, + table_name: 'journal_entry', + 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; } else { @@ -588,14 +607,18 @@ export async function update_ae_obj__journal_entry({ if (log_lvl) { console.log('Processed object list:', processed_obj_li); } - // Save the updated results list to the database - await db_save_ae_obj_li__ae_obj({ - db_instance: db_journals, - table_name: 'journal_entry', - obj_li: processed_obj_li, - properties_to_save: properties_to_save, - 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({ + db_instance: db_journals, + table_name: 'journal_entry', + 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 result; } else { @@ -848,13 +871,13 @@ const properties_to_save = [ // 'description', 'content', - 'content_md_html', + // content_md_html is computed from content on every load — not stored to save IDB quota 'content_html', 'content_json', 'content_encrypted', 'history', - 'history_md_html', + // history_md_html is computed from history on every load — not stored to save IDB quota 'history_encrypted', 'passcode_hash',