first commit
This commit is contained in:
commit
68b9860855
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
*.pyc
|
||||||
|
*.pyo
|
||||||
|
*~
|
||||||
|
__pycache__/
|
||||||
10
README.md
Normal file
10
README.md
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
POS IndexedDB Patch
|
||||||
|
===================
|
||||||
|
|
||||||
|
This module patches Odoo's bus Logger to avoid IndexedDB connection crashes.
|
||||||
|
|
||||||
|
Features
|
||||||
|
--------
|
||||||
|
- Automatically recreates database connection if closing or closed.
|
||||||
|
- Adds error safety handlers to log writes and reads.
|
||||||
|
- Works in both browser thread and shared/web worker threads.
|
||||||
2
__init__.py
Normal file
2
__init__.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||||
26
__manifest__.py
Normal file
26
__manifest__.py
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
'name': 'POS IndexedDB Patch',
|
||||||
|
'version': '19.0.1.0.0',
|
||||||
|
'category': 'Technical',
|
||||||
|
'summary': 'Patches IndexedDB Logger connection issues in bus worker and main thread',
|
||||||
|
'description': """
|
||||||
|
This module patches the Logger class inside the bus module to handle IndexedDB connection closures gracefully, preventing POS crashes when the browser suspends/hibernates database connections.
|
||||||
|
""",
|
||||||
|
'author': 'Suherdy Yacob',
|
||||||
|
'depends': ['bus', 'point_of_sale'],
|
||||||
|
'data': [],
|
||||||
|
'assets': {
|
||||||
|
'web.assets_backend': [
|
||||||
|
'pos_indexeddb_patch/static/src/workers/patch_logger.js',
|
||||||
|
],
|
||||||
|
'web.assets_frontend': [
|
||||||
|
'pos_indexeddb_patch/static/src/workers/patch_logger.js',
|
||||||
|
],
|
||||||
|
'bus.websocket_worker_assets': [
|
||||||
|
'pos_indexeddb_patch/static/src/workers/patch_logger.js',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
'installable': True,
|
||||||
|
'auto_install': False,
|
||||||
|
'license': 'LGPL-3',
|
||||||
|
}
|
||||||
84
static/src/workers/patch_logger.js
Normal file
84
static/src/workers/patch_logger.js
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
import { Logger } from "@bus/workers/bus_worker_utils";
|
||||||
|
|
||||||
|
function patchLogger(LoggerClass) {
|
||||||
|
if (!LoggerClass || LoggerClass.prototype._patchedByIndexedDbPatch) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
LoggerClass.prototype._patchedByIndexedDbPatch = true;
|
||||||
|
|
||||||
|
LoggerClass.prototype._ensureDatabaseAvailable = async function() {
|
||||||
|
if (this._db) {
|
||||||
|
try {
|
||||||
|
this._db.transaction("logs", "readonly");
|
||||||
|
} catch (e) {
|
||||||
|
this._db = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this._db) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
const request = indexedDB.open(this._name, 1);
|
||||||
|
request.onsuccess = (event) => {
|
||||||
|
this._db = event.target.result;
|
||||||
|
this._db.onversionchange = () => {
|
||||||
|
this._db.close();
|
||||||
|
this._db = null;
|
||||||
|
};
|
||||||
|
this._db.onclose = () => {
|
||||||
|
this._db = null;
|
||||||
|
};
|
||||||
|
res();
|
||||||
|
};
|
||||||
|
request.onupgradeneeded = (event) => {
|
||||||
|
if (!event.target.result.objectStoreNames.contains("logs")) {
|
||||||
|
const store = event.target.result.createObjectStore("logs", {
|
||||||
|
autoIncrement: true,
|
||||||
|
});
|
||||||
|
store.createIndex("timestamp", "timestamp", { unique: false });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
request.onerror = rej;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
LoggerClass.prototype.log = async function(message) {
|
||||||
|
try {
|
||||||
|
await this._ensureDatabaseAvailable();
|
||||||
|
if (!this._db) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const transaction = this._db.transaction("logs", "readwrite");
|
||||||
|
const store = transaction.objectStore("logs");
|
||||||
|
const addRequest = store.add({ timestamp: Date.now(), message });
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
addRequest.onsuccess = res;
|
||||||
|
addRequest.onerror = rej;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to write log to IndexedDB:", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
LoggerClass.prototype.getLogs = async function() {
|
||||||
|
try {
|
||||||
|
await LoggerClass.gcOutdatedLogs();
|
||||||
|
await this._ensureDatabaseAvailable();
|
||||||
|
if (!this._db) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
const transaction = this._db.transaction("logs", "readonly");
|
||||||
|
const store = transaction.objectStore("logs");
|
||||||
|
const request = store.getAll();
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
request.onsuccess = (ev) => res(ev.target.result.map(({ message }) => message));
|
||||||
|
request.onerror = rej;
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to retrieve logs from IndexedDB:", error);
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
patchLogger(Logger);
|
||||||
Loading…
Reference in New Issue
Block a user