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],
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 {

View File

@@ -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',