|
5 | 5 | from typing import List, Optional, Set, cast
|
6 | 6 |
|
7 | 7 | import git
|
| 8 | +from ddtrace import tracer |
8 | 9 | from fastapi_websocket_pubsub import PubSubEndpoint
|
9 | 10 | from opal_common.git.commit_viewer import VersionedFile
|
10 | 11 | from opal_common.logger import logger
|
@@ -122,102 +123,105 @@ async def sync_scope(
|
122 | 123 | assert scope_id, ValueError("scope_id not set for sync_scope")
|
123 | 124 | scope = await self._scopes.get(scope_id)
|
124 | 125 |
|
125 |
| - if not isinstance(scope.policy, GitPolicyScopeSource): |
126 |
| - logger.warning("Non-git scopes are currently not supported!") |
127 |
| - return |
128 |
| - source = cast(GitPolicyScopeSource, scope.policy) |
129 |
| - |
130 |
| - logger.debug( |
131 |
| - f"Sync scope: {scope.scope_id} (remote: {source.url}, branch: {source.branch}, req_time: {req_time})" |
132 |
| - ) |
133 |
| - |
134 |
| - callbacks = PolicyFetcherCallbacks() |
135 |
| - if notify_on_changes: |
136 |
| - callbacks = NewCommitsCallbacks( |
137 |
| - base_dir=self._base_dir, |
138 |
| - scope_id=scope.scope_id, |
139 |
| - source=source, |
140 |
| - pubsub_endpoint=self._pubsub_endpoint, |
141 |
| - ) |
142 |
| - |
143 |
| - fetcher = GitPolicyFetcher( |
144 |
| - self._base_dir, |
145 |
| - scope.scope_id, |
146 |
| - source, |
147 |
| - callbacks=callbacks, |
148 |
| - ) |
| 126 | + with tracer.trace("scopes_service.sync_scope", resource=scope.scope_id): |
| 127 | + if not isinstance(scope.policy, GitPolicyScopeSource): |
| 128 | + logger.warning("Non-git scopes are currently not supported!") |
| 129 | + return |
| 130 | + source = cast(GitPolicyScopeSource, scope.policy) |
149 | 131 |
|
150 |
| - try: |
151 |
| - await fetcher.fetch_and_notify_on_changes( |
152 |
| - hinted_hash=hinted_hash, force_fetch=force_fetch, req_time=req_time |
153 |
| - ) |
154 |
| - except Exception as e: |
155 |
| - logger.exception( |
156 |
| - f"Could not fetch policy for scope {scope.scope_id}, got error: {e}" |
| 132 | + logger.debug( |
| 133 | + f"Sync scope: {scope.scope_id} (remote: {source.url}, branch: {source.branch}, req_time: {req_time})" |
157 | 134 | )
|
158 | 135 |
|
159 |
| - async def delete_scope(self, scope_id: str): |
160 |
| - logger.info(f"Delete scope: {scope_id}") |
161 |
| - scope = await self._scopes.get(scope_id) |
162 |
| - url = scope.policy.url |
163 |
| - |
164 |
| - scopes = await self._scopes.all() |
165 |
| - remove_repo_clone = True |
166 |
| - |
167 |
| - for scope in scopes: |
168 |
| - if scope.scope_id != scope_id and scope.policy.url == url: |
169 |
| - logger.info( |
170 |
| - f"found another scope with same remote url ({scope.scope_id}), skipping clone deletion" |
| 136 | + callbacks = PolicyFetcherCallbacks() |
| 137 | + if notify_on_changes: |
| 138 | + callbacks = NewCommitsCallbacks( |
| 139 | + base_dir=self._base_dir, |
| 140 | + scope_id=scope.scope_id, |
| 141 | + source=source, |
| 142 | + pubsub_endpoint=self._pubsub_endpoint, |
171 | 143 | )
|
172 |
| - remove_repo_clone = False |
173 |
| - break |
174 | 144 |
|
175 |
| - if remove_repo_clone: |
176 |
| - scope_dir = GitPolicyFetcher.repo_clone_path( |
177 |
| - self._base_dir, cast(GitPolicyScopeSource, scope.policy) |
| 145 | + fetcher = GitPolicyFetcher( |
| 146 | + self._base_dir, |
| 147 | + scope.scope_id, |
| 148 | + source, |
| 149 | + callbacks=callbacks, |
178 | 150 | )
|
179 |
| - shutil.rmtree(scope_dir, ignore_errors=True) |
180 |
| - |
181 |
| - await self._scopes.delete(scope_id) |
182 |
| - |
183 |
| - async def sync_scopes(self, only_poll_updates=False, notify_on_changes=True): |
184 |
| - scopes = await self._scopes.all() |
185 |
| - if only_poll_updates: |
186 |
| - # Only sync scopes that have polling enabled (in a periodic check) |
187 |
| - scopes = [scope for scope in scopes if scope.policy.poll_updates] |
188 |
| - |
189 |
| - logger.info( |
190 |
| - f"OPAL Scopes: syncing {len(scopes)} scopes in the background (polling updates: {only_poll_updates})" |
191 |
| - ) |
192 |
| - |
193 |
| - fetched_source_ids = set() |
194 |
| - skipped_scopes = [] |
195 |
| - for scope in scopes: |
196 |
| - src_id = GitPolicyFetcher.source_id(scope.policy) |
197 |
| - |
198 |
| - # Give priority to scopes that have a unique url per shard (so we'll clone all repos asap) |
199 |
| - if src_id in fetched_source_ids: |
200 |
| - skipped_scopes.append(scope) |
201 |
| - continue |
202 | 151 |
|
203 | 152 | try:
|
204 |
| - await self.sync_scope( |
205 |
| - scope=scope, |
206 |
| - force_fetch=True, |
207 |
| - notify_on_changes=notify_on_changes, |
| 153 | + await fetcher.fetch_and_notify_on_changes( |
| 154 | + hinted_hash=hinted_hash, force_fetch=force_fetch, req_time=req_time |
208 | 155 | )
|
209 | 156 | except Exception as e:
|
210 |
| - logger.exception(f"sync_scope failed for {scope.scope_id}") |
211 |
| - |
212 |
| - fetched_source_ids.add(src_id) |
| 157 | + logger.exception( |
| 158 | + f"Could not fetch policy for scope {scope.scope_id}, got error: {e}" |
| 159 | + ) |
213 | 160 |
|
214 |
| - for scope in skipped_scopes: |
215 |
| - # No need to refetch the same repo, just check for changes |
216 |
| - try: |
217 |
| - await self.sync_scope( |
218 |
| - scope=scope, |
219 |
| - force_fetch=False, |
220 |
| - notify_on_changes=notify_on_changes, |
| 161 | + async def delete_scope(self, scope_id: str): |
| 162 | + with tracer.trace("scopes_service.delete_scope", resource=scope_id): |
| 163 | + logger.info(f"Delete scope: {scope_id}") |
| 164 | + scope = await self._scopes.get(scope_id) |
| 165 | + url = scope.policy.url |
| 166 | + |
| 167 | + scopes = await self._scopes.all() |
| 168 | + remove_repo_clone = True |
| 169 | + |
| 170 | + for scope in scopes: |
| 171 | + if scope.scope_id != scope_id and scope.policy.url == url: |
| 172 | + logger.info( |
| 173 | + f"found another scope with same remote url ({scope.scope_id}), skipping clone deleteion" |
| 174 | + ) |
| 175 | + remove_repo_clone = False |
| 176 | + break |
| 177 | + |
| 178 | + if remove_repo_clone: |
| 179 | + scope_dir = GitPolicyFetcher.repo_clone_path( |
| 180 | + self._base_dir, cast(GitPolicyScopeSource, scope.policy) |
221 | 181 | )
|
222 |
| - except Exception as e: |
223 |
| - logger.exception(f"sync_scope failed for {scope.scope_id}") |
| 182 | + shutil.rmtree(scope_dir, ignore_errors=True) |
| 183 | + |
| 184 | + await self._scopes.delete(scope_id) |
| 185 | + |
| 186 | + async def sync_scopes(self, only_poll_updates=False, notify_on_changes=True): |
| 187 | + with tracer.trace("scopes_service.sync_scopes"): |
| 188 | + scopes = await self._scopes.all() |
| 189 | + if only_poll_updates: |
| 190 | + # Only sync scopes that have polling enabled (in a periodic check) |
| 191 | + scopes = [scope for scope in scopes if scope.policy.poll_updates] |
| 192 | + |
| 193 | + logger.info( |
| 194 | + f"OPAL Scopes: syncing {len(scopes)} scopes in the background (polling updates: {only_poll_updates})" |
| 195 | + ) |
| 196 | + |
| 197 | + fetched_source_ids = set() |
| 198 | + skipped_scopes = [] |
| 199 | + for scope in scopes: |
| 200 | + src_id = GitPolicyFetcher.source_id(scope.policy) |
| 201 | + |
| 202 | + # Give priority to scopes that have a unique url per shard (so we'll clone all repos asap) |
| 203 | + if src_id in fetched_source_ids: |
| 204 | + skipped_scopes.append(scope) |
| 205 | + continue |
| 206 | + |
| 207 | + try: |
| 208 | + await self.sync_scope( |
| 209 | + scope=scope, |
| 210 | + force_fetch=True, |
| 211 | + notify_on_changes=notify_on_changes, |
| 212 | + ) |
| 213 | + except Exception as e: |
| 214 | + logger.exception(f"sync_scope failed for {scope.scope_id}") |
| 215 | + |
| 216 | + fetched_source_ids.add(src_id) |
| 217 | + |
| 218 | + for scope in skipped_scopes: |
| 219 | + # No need to refetch the same repo, just check for changes |
| 220 | + try: |
| 221 | + await self.sync_scope( |
| 222 | + scope=scope, |
| 223 | + force_fetch=False, |
| 224 | + notify_on_changes=notify_on_changes, |
| 225 | + ) |
| 226 | + except Exception as e: |
| 227 | + logger.exception(f"sync_scope failed for {scope.scope_id}") |
0 commit comments