|
13 | 13 | import logging
|
14 | 14 | import shutil
|
15 | 15 | import sqlite3
|
| 16 | +import time |
16 | 17 | import tempfile
|
17 | 18 | from datetime import date
|
18 | 19 | from os import utime
|
|
49 | 50 | EPSS_METRIC_ID = 1
|
50 | 51 | CVSS_2_METRIC_ID = 2
|
51 | 52 | CVSS_3_METRIC_ID = 3
|
52 |
| - |
| 53 | +MAX_RETRIES = 5 # Number of retries before failing |
| 54 | +RETRY_DELAY = 0.5 # Initial delay in seconds (will double on each retry) |
53 | 55 |
|
54 | 56 | class CVEDB:
|
55 | 57 | """
|
@@ -763,18 +765,23 @@ def update_vendors(self, cve_data):
|
763 | 765 |
|
764 | 766 | return updated_severity, updated_affected
|
765 | 767 |
|
766 |
| - def db_open_and_get_cursor(self) -> sqlite3.Cursor: |
767 |
| - """Opens connection to sqlite database, returns cursor object.""" |
768 |
| - |
769 |
| - if not self.connection: |
770 |
| - self.connection = sqlite3.connect(self.dbpath) |
771 |
| - if self.connection is not None: |
772 |
| - cursor = self.connection.cursor() |
773 |
| - if cursor is None: |
774 |
| - # if this happens somsething has gone horribly wrong |
775 |
| - LOGGER.error("Database cursor does not exist") |
776 |
| - raise CVEDBError |
777 |
| - return cursor |
| 768 | + def db_open_and_get_cursor(self): |
| 769 | + """Open the database connection with retry logic to handle 'database is locked' errors.""" |
| 770 | + retries = 0 |
| 771 | + while retries < MAX_RETRIES: |
| 772 | + try: |
| 773 | + self.connection = sqlite3.connect(self.dbpath, timeout=10) # Extend timeout |
| 774 | + self.connection.execute("PRAGMA journal_mode=WAL;") # Improve concurrency |
| 775 | + return self.connection.cursor() |
| 776 | + except sqlite3.OperationalError as e: |
| 777 | + if "database is locked" in str(e): |
| 778 | + retries += 1 |
| 779 | + wait_time = RETRY_DELAY * (2 ** retries) # Exponential backoff |
| 780 | + print(f"Database locked, retrying in {wait_time:.2f} seconds...") |
| 781 | + time.sleep(wait_time) |
| 782 | + else: |
| 783 | + raise # Raise other errors |
| 784 | + raise sqlite3.OperationalError("Database is locked, retry limit reached.") |
778 | 785 |
|
779 | 786 | def db_close(self) -> None:
|
780 | 787 | """Closes connection to sqlite database."""
|
|
0 commit comments