maintenance.py 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import logging
  2. from core.base import Handler
  3. from .base import PostgresConnectionManager
  4. logger = logging.getLogger(__name__)
  5. class PostgresMaintenanceHandler(Handler):
  6. def __init__(
  7. self,
  8. project_name: str,
  9. connection_manager: PostgresConnectionManager,
  10. ):
  11. """
  12. Initialize the PostgresMaintenanceHandler with the given project name and connection manager.
  13. Args:
  14. project_name (str): The name of the project.
  15. connection_manager (PostgresConnectionManager): The connection manager to use.
  16. """
  17. super().__init__(project_name, connection_manager)
  18. logger.debug(
  19. f"Initialized PostgresMaintenanceHandler for project: {project_name}"
  20. )
  21. async def create_tables(self):
  22. pass
  23. async def vacuum_table(
  24. self,
  25. table_name: str,
  26. analyze: bool = False,
  27. full: bool = False,
  28. ):
  29. """
  30. VACUUM reclaims storage occupied by dead tuples. In normal PostgreSQL operation,
  31. tuples that are deleted or obsoleted by an update are not physically removed from
  32. their table; they remain present until a VACUUM is done.
  33. Therefore it's necessary to do VACUUM periodically, especially on frequently-updated
  34. tables.
  35. VACUUM ANALYZE performs a VACUUM and then an ANALYZE for each selected table.
  36. Plain VACUUM (without FULL) simply reclaims space and makes it available for re-use.
  37. This form of the command can operate in parallel with normal reading and writing of the
  38. table, as an exclusive lock is not obtained. However, extra space is not returned to
  39. the operating system (in most cases); it's just kept available for re-use within the same
  40. table.
  41. VACUUM FULL rewrites the entire contents of the table into a new disk file with no extra
  42. space, allowing unused space to be returned to the operating system. This form is much
  43. slower and requires an ACCESS EXCLUSIVE lock on each table while it is being processed.
  44. TODO: Implement VACUUM FULL
  45. """
  46. vacuum_query = "VACUUM"
  47. if analyze:
  48. vacuum_query += " ANALYZE"
  49. if full:
  50. logger.warning(
  51. "VACUUM FULL not implemented yet. Running plain VACUUM instead."
  52. )
  53. try:
  54. await self.connection_manager.execute_query(
  55. f"{vacuum_query} {table_name}"
  56. )
  57. except Exception as e:
  58. logger.error(f"Error vacuuming table {table_name}: {str(e)}")
  59. raise e
  60. async def vacuum_all_tables(
  61. self,
  62. analyze: bool = False,
  63. full: bool = False,
  64. ):
  65. """Vacuum all tables in the database"""
  66. vacuum_query = "VACUUM"
  67. if analyze:
  68. vacuum_query += " ANALYZE"
  69. if full:
  70. logger.warning(
  71. "VACUUM FULL not implemented yet. Running plain VACUUM instead."
  72. )
  73. try:
  74. await self.connection_manager.execute_query(vacuum_query)
  75. except Exception as e:
  76. logger.error(f"Error vacuuming all tables: {str(e)}")
  77. raise e