33"""An SQLAlchemy backend for the search endpoint
44"""
55
6+ import logging
7+
68from ... import storage
79from ... import toolkit
810from .. import config
1416import sqlalchemy .sql .functions
1517
1618
19+ logger = logging .getLogger (__name__ )
20+
21+
1722Base = sqlalchemy .ext .declarative .declarative_base ()
1823
1924
@@ -43,6 +48,24 @@ def __repr__(self):
4348 type (self ).__name__ , self .name , self .description )
4449
4550
51+ def retry (f ):
52+ def _retry (self , * args , ** kwargs ):
53+ retry_times = 1
54+ i = 0
55+ while True :
56+ try :
57+ return f (self , * args , ** kwargs )
58+ except sqlalchemy .exc .DBAPIError as e :
59+ if i < retry_times :
60+ logger .warn ("DB is disconnected. Reconnect to it." )
61+ self .reconnect_db ()
62+ i += 1
63+ else :
64+ raise e
65+
66+ return _retry
67+
68+
4669class SQLAlchemyIndex (Index ):
4770 """Maintain an index of repository data
4871
@@ -56,12 +79,17 @@ def __init__(self, database=None):
5679 if database is None :
5780 cfg = config .load ()
5881 database = cfg .sqlalchemy_index_database
82+ self ._database = database
5983 self ._engine = sqlalchemy .create_engine (database )
6084 self ._session = sqlalchemy .orm .sessionmaker (bind = self ._engine )
6185 self .version = 1
6286 self ._setup_database ()
6387 super (SQLAlchemyIndex , self ).__init__ ()
6488
89+ def reconnect_db (self ):
90+ self ._engine = sqlalchemy .create_engine (self ._database )
91+ self ._session = sqlalchemy .orm .sessionmaker (bind = self ._engine )
92+
6593 @toolkit .exclusive_lock
6694 def _setup_database (self ):
6795 session = self ._session ()
@@ -78,6 +106,7 @@ def _setup_database(self):
78106 self ._generate_index (session = session )
79107 session .close ()
80108
109+ @retry
81110 def _generate_index (self , session ):
82111 store = storage .load ()
83112 Base .metadata .create_all (self ._engine )
@@ -86,6 +115,7 @@ def _generate_index(self, session):
86115 session .add (Repository (** repository ))
87116 session .commit ()
88117
118+ @retry
89119 def _handle_repository_created (
90120 self , sender , namespace , repository , value ):
91121 name = '{0}/{1}' .format (namespace , repository )
@@ -95,6 +125,7 @@ def _handle_repository_created(
95125 session .commit ()
96126 session .close ()
97127
128+ @retry
98129 def _handle_repository_updated (
99130 self , sender , namespace , repository , value ):
100131 name = '{0}/{1}' .format (namespace , repository )
@@ -109,13 +140,15 @@ def _handle_repository_updated(
109140 session .commit ()
110141 session .close ()
111142
143+ @retry
112144 def _handle_repository_deleted (self , sender , namespace , repository ):
113145 name = '{0}/{1}' .format (namespace , repository )
114146 session = self ._session ()
115147 session .query (Repository ).filter (Repository .name == name ).delete ()
116148 session .commit ()
117149 session .close ()
118150
151+ @retry
119152 def results (self , search_term = None ):
120153 session = self ._session ()
121154 repositories = session .query (Repository )
0 commit comments