from concurrent.futures import ThreadPoolExecutor
import sqlite3


TASK_RUNTIME_ERRORS = (
    RuntimeError,
    ValueError,
    TypeError,
    KeyError,
    AttributeError,
    LookupError,
    ArithmeticError,
    OSError,
    # edited by glg
    # Pastikan error SQLite dari worker async diteruskan ke on_error,
    # bukan bocor sebagai traceback callback concurrent.futures.
    sqlite3.Error,
)


class TransaksiBackgroundTaskService:
    def __init__(self, max_workers=2):
        self._executor = ThreadPoolExecutor(max_workers=max(1, int(max_workers or 1)))

    def run(self, task, *args, on_done=None, on_error=None, **kwargs):
        future = self._executor.submit(task, *args, **kwargs)
        if callable(on_done) or callable(on_error):
            def _callback(done_future):
                try:
                    result = done_future.result()
                    if callable(on_done):
                        on_done(result)
                except TASK_RUNTIME_ERRORS as exc:
                    if callable(on_error):
                        on_error(exc)
            future.add_done_callback(_callback)
        return future

    def shutdown(self, wait=False):
        self._executor.shutdown(wait=bool(wait))
