kodit 0.5.4__py3-none-any.whl → 0.5.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of kodit might be problematic. Click here for more details.
- kodit/_version.py +2 -2
- kodit/application/factories/server_factory.py +54 -32
- kodit/application/services/code_search_application_service.py +89 -12
- kodit/application/services/commit_indexing_application_service.py +314 -195
- kodit/application/services/enrichment_query_service.py +274 -43
- kodit/application/services/indexing_worker_service.py +1 -1
- kodit/application/services/queue_service.py +15 -10
- kodit/application/services/sync_scheduler.py +2 -1
- kodit/domain/enrichments/architecture/architecture.py +1 -1
- kodit/domain/enrichments/architecture/physical/physical.py +1 -1
- kodit/domain/enrichments/development/development.py +1 -1
- kodit/domain/enrichments/development/snippet/snippet.py +12 -5
- kodit/domain/enrichments/enrichment.py +31 -4
- kodit/domain/enrichments/usage/api_docs.py +1 -1
- kodit/domain/enrichments/usage/usage.py +1 -1
- kodit/domain/entities/git.py +30 -25
- kodit/domain/factories/git_repo_factory.py +20 -5
- kodit/domain/protocols.py +56 -125
- kodit/domain/services/embedding_service.py +14 -16
- kodit/domain/services/git_repository_service.py +60 -38
- kodit/domain/services/git_service.py +18 -11
- kodit/domain/tracking/resolution_service.py +6 -16
- kodit/domain/value_objects.py +2 -9
- kodit/infrastructure/api/v1/dependencies.py +12 -3
- kodit/infrastructure/api/v1/query_params.py +27 -0
- kodit/infrastructure/api/v1/routers/commits.py +91 -85
- kodit/infrastructure/api/v1/routers/repositories.py +53 -37
- kodit/infrastructure/api/v1/routers/search.py +1 -1
- kodit/infrastructure/api/v1/schemas/enrichment.py +14 -0
- kodit/infrastructure/api/v1/schemas/repository.py +1 -1
- kodit/infrastructure/slicing/api_doc_extractor.py +0 -2
- kodit/infrastructure/sqlalchemy/embedding_repository.py +44 -34
- kodit/infrastructure/sqlalchemy/enrichment_association_repository.py +73 -0
- kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py +116 -97
- kodit/infrastructure/sqlalchemy/entities.py +12 -116
- kodit/infrastructure/sqlalchemy/git_branch_repository.py +52 -244
- kodit/infrastructure/sqlalchemy/git_commit_repository.py +35 -324
- kodit/infrastructure/sqlalchemy/git_file_repository.py +70 -0
- kodit/infrastructure/sqlalchemy/git_repository.py +60 -230
- kodit/infrastructure/sqlalchemy/git_tag_repository.py +53 -240
- kodit/infrastructure/sqlalchemy/query.py +331 -0
- kodit/infrastructure/sqlalchemy/repository.py +203 -0
- kodit/infrastructure/sqlalchemy/task_repository.py +79 -58
- kodit/infrastructure/sqlalchemy/task_status_repository.py +45 -52
- kodit/migrations/versions/4b1a3b2c8fa5_refactor_git_tracking.py +190 -0
- {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/METADATA +1 -1
- {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/RECORD +50 -48
- kodit/infrastructure/mappers/enrichment_mapper.py +0 -83
- kodit/infrastructure/mappers/git_mapper.py +0 -193
- kodit/infrastructure/mappers/snippet_mapper.py +0 -104
- kodit/infrastructure/sqlalchemy/snippet_v2_repository.py +0 -479
- {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/WHEEL +0 -0
- {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/entry_points.txt +0 -0
- {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,47 +2,67 @@
|
|
|
2
2
|
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
-
from kodit.domain.enrichments.
|
|
5
|
+
from kodit.domain.enrichments.architecture.architecture import (
|
|
6
|
+
ENRICHMENT_TYPE_ARCHITECTURE,
|
|
7
|
+
)
|
|
8
|
+
from kodit.domain.enrichments.architecture.physical.physical import (
|
|
9
|
+
ENRICHMENT_SUBTYPE_PHYSICAL,
|
|
10
|
+
)
|
|
11
|
+
from kodit.domain.enrichments.development.development import ENRICHMENT_TYPE_DEVELOPMENT
|
|
12
|
+
from kodit.domain.enrichments.development.snippet.snippet import (
|
|
13
|
+
ENRICHMENT_SUBTYPE_SNIPPET,
|
|
14
|
+
ENRICHMENT_SUBTYPE_SNIPPET_SUMMARY,
|
|
15
|
+
)
|
|
16
|
+
from kodit.domain.enrichments.enrichment import EnrichmentAssociation, EnrichmentV2
|
|
17
|
+
from kodit.domain.enrichments.usage.api_docs import ENRICHMENT_SUBTYPE_API_DOCS
|
|
18
|
+
from kodit.domain.enrichments.usage.usage import ENRICHMENT_TYPE_USAGE
|
|
19
|
+
from kodit.domain.protocols import (
|
|
20
|
+
EnrichmentAssociationRepository,
|
|
21
|
+
EnrichmentV2Repository,
|
|
22
|
+
)
|
|
6
23
|
from kodit.domain.tracking.resolution_service import TrackableResolutionService
|
|
7
24
|
from kodit.domain.tracking.trackable import Trackable
|
|
8
|
-
from kodit.infrastructure.
|
|
9
|
-
|
|
25
|
+
from kodit.infrastructure.api.v1.query_params import PaginationParams
|
|
26
|
+
from kodit.infrastructure.sqlalchemy import entities as db_entities
|
|
27
|
+
from kodit.infrastructure.sqlalchemy.query import (
|
|
28
|
+
EnrichmentAssociationQueryBuilder,
|
|
29
|
+
EnrichmentQueryBuilder,
|
|
10
30
|
)
|
|
11
31
|
|
|
12
32
|
|
|
13
33
|
class EnrichmentQueryService:
|
|
14
|
-
"""
|
|
15
|
-
|
|
16
|
-
Orchestrates domain services and repositories to fulfill the use case.
|
|
17
|
-
"""
|
|
34
|
+
"""Service for querying enrichments."""
|
|
18
35
|
|
|
19
36
|
def __init__(
|
|
20
37
|
self,
|
|
21
38
|
trackable_resolution: TrackableResolutionService,
|
|
22
39
|
enrichment_repo: EnrichmentV2Repository,
|
|
40
|
+
enrichment_association_repository: EnrichmentAssociationRepository,
|
|
23
41
|
) -> None:
|
|
24
42
|
"""Initialize the enrichment query service."""
|
|
25
43
|
self.trackable_resolution = trackable_resolution
|
|
26
44
|
self.enrichment_repo = enrichment_repo
|
|
45
|
+
self.enrichment_association_repository = enrichment_association_repository
|
|
27
46
|
self.log = structlog.get_logger(__name__)
|
|
28
47
|
|
|
48
|
+
async def associations_for_commit(
|
|
49
|
+
self, commit_sha: str
|
|
50
|
+
) -> list[EnrichmentAssociation]:
|
|
51
|
+
"""Get enrichments for a commit."""
|
|
52
|
+
return await self.enrichment_association_repository.find(
|
|
53
|
+
EnrichmentAssociationQueryBuilder.for_enrichment_associations(
|
|
54
|
+
entity_type=db_entities.GitCommit.__tablename__,
|
|
55
|
+
entity_ids=[commit_sha],
|
|
56
|
+
)
|
|
57
|
+
)
|
|
58
|
+
|
|
29
59
|
async def find_latest_enriched_commit(
|
|
30
60
|
self,
|
|
31
61
|
trackable: Trackable,
|
|
32
62
|
enrichment_type: str | None = None,
|
|
33
63
|
max_commits_to_check: int = 100,
|
|
34
64
|
) -> str | None:
|
|
35
|
-
"""Find the most recent commit with enrichments.
|
|
36
|
-
|
|
37
|
-
Args:
|
|
38
|
-
trackable: What to track (branch, tag, or commit)
|
|
39
|
-
enrichment_type: Optional filter for specific enrichment type
|
|
40
|
-
max_commits_to_check: How far back in history to search
|
|
41
|
-
|
|
42
|
-
Returns:
|
|
43
|
-
Commit SHA of the most recent commit with enrichments, or None
|
|
44
|
-
|
|
45
|
-
"""
|
|
65
|
+
"""Find the most recent commit with enrichments."""
|
|
46
66
|
# Get candidate commits from the trackable
|
|
47
67
|
candidate_commits = await self.trackable_resolution.resolve_to_commits(
|
|
48
68
|
trackable, max_commits_to_check
|
|
@@ -52,44 +72,255 @@ class EnrichmentQueryService:
|
|
|
52
72
|
return None
|
|
53
73
|
|
|
54
74
|
# Check which commits have enrichments
|
|
55
|
-
enrichments = await self.enrichment_repo.enrichments_for_entity_type(
|
|
56
|
-
entity_type="git_commit",
|
|
57
|
-
entity_ids=candidate_commits,
|
|
58
|
-
)
|
|
59
|
-
|
|
60
|
-
# Filter by type if specified
|
|
61
|
-
if enrichment_type:
|
|
62
|
-
enrichments = [e for e in enrichments if e.type == enrichment_type]
|
|
63
|
-
|
|
64
|
-
# Find the first commit (newest) that has enrichments
|
|
65
75
|
for commit_sha in candidate_commits:
|
|
66
|
-
|
|
76
|
+
enrichments = await self.all_enrichments_for_commit(
|
|
77
|
+
commit_sha=commit_sha,
|
|
78
|
+
pagination=PaginationParams(page_size=1),
|
|
79
|
+
enrichment_type=enrichment_type,
|
|
80
|
+
)
|
|
81
|
+
if enrichments:
|
|
67
82
|
return commit_sha
|
|
68
83
|
|
|
69
84
|
return None
|
|
70
85
|
|
|
86
|
+
async def all_enrichments_for_commit(
|
|
87
|
+
self,
|
|
88
|
+
commit_sha: str,
|
|
89
|
+
pagination: PaginationParams,
|
|
90
|
+
enrichment_type: str | None = None,
|
|
91
|
+
enrichment_subtype: str | None = None,
|
|
92
|
+
) -> dict[EnrichmentV2, list[EnrichmentAssociation]]:
|
|
93
|
+
"""Get all enrichments for a specific commit."""
|
|
94
|
+
associations = await self.enrichment_association_repository.find(
|
|
95
|
+
EnrichmentAssociationQueryBuilder().for_commit(commit_sha)
|
|
96
|
+
)
|
|
97
|
+
enrichment_ids = [association.enrichment_id for association in associations]
|
|
98
|
+
query = EnrichmentQueryBuilder().for_ids(enrichment_ids).paginate(pagination)
|
|
99
|
+
if enrichment_type:
|
|
100
|
+
query = query.for_type(enrichment_type)
|
|
101
|
+
if enrichment_subtype:
|
|
102
|
+
query = query.for_subtype(enrichment_subtype)
|
|
103
|
+
enrichments = await self.enrichment_repo.find(query)
|
|
104
|
+
# Find all other associations for these enrichments
|
|
105
|
+
other_associations = await self.enrichment_association_repository.find(
|
|
106
|
+
EnrichmentAssociationQueryBuilder().for_enrichments(enrichments)
|
|
107
|
+
)
|
|
108
|
+
all_associations = set(associations + other_associations)
|
|
109
|
+
return {
|
|
110
|
+
enrichment: [
|
|
111
|
+
association
|
|
112
|
+
for association in all_associations
|
|
113
|
+
if association.enrichment_id == enrichment.id
|
|
114
|
+
or association.entity_id == str(enrichment.id)
|
|
115
|
+
]
|
|
116
|
+
for enrichment in enrichments
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async def get_all_snippets_for_commit(self, commit_sha: str) -> list[EnrichmentV2]:
|
|
120
|
+
"""Get snippet enrichments for a commit."""
|
|
121
|
+
return list(
|
|
122
|
+
await self.all_enrichments_for_commit(
|
|
123
|
+
commit_sha=commit_sha,
|
|
124
|
+
pagination=PaginationParams(page_size=32000),
|
|
125
|
+
enrichment_type=ENRICHMENT_TYPE_DEVELOPMENT,
|
|
126
|
+
enrichment_subtype=ENRICHMENT_SUBTYPE_SNIPPET,
|
|
127
|
+
)
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
async def get_summaries_for_commit(self, commit_sha: str) -> list[EnrichmentV2]:
|
|
131
|
+
"""Get summary enrichments for a commit."""
|
|
132
|
+
return await self.get_enrichments_for_commit(
|
|
133
|
+
commit_sha,
|
|
134
|
+
enrichment_type=ENRICHMENT_TYPE_DEVELOPMENT,
|
|
135
|
+
enrichment_subtype=ENRICHMENT_SUBTYPE_SNIPPET_SUMMARY,
|
|
136
|
+
)
|
|
137
|
+
|
|
71
138
|
async def get_enrichments_for_commit(
|
|
72
139
|
self,
|
|
73
140
|
commit_sha: str,
|
|
74
141
|
enrichment_type: str | None = None,
|
|
142
|
+
enrichment_subtype: str | None = None,
|
|
75
143
|
) -> list[EnrichmentV2]:
|
|
76
|
-
"""Get
|
|
144
|
+
"""Get enrichments for a commit."""
|
|
145
|
+
# Find associations pointing to this commit
|
|
146
|
+
all_associations = await self.enrichment_association_repository.find(
|
|
147
|
+
EnrichmentAssociationQueryBuilder().for_commit(commit_sha)
|
|
148
|
+
)
|
|
149
|
+
query = EnrichmentQueryBuilder().for_ids(
|
|
150
|
+
enrichment_ids=[
|
|
151
|
+
int(association.enrichment_id) for association in all_associations
|
|
152
|
+
]
|
|
153
|
+
)
|
|
154
|
+
if enrichment_type:
|
|
155
|
+
query = query.for_type(enrichment_type)
|
|
156
|
+
if enrichment_subtype:
|
|
157
|
+
query = query.for_subtype(enrichment_subtype)
|
|
158
|
+
return await self.enrichment_repo.find(query)
|
|
77
159
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
160
|
+
async def get_architecture_docs_for_commit(
|
|
161
|
+
self, commit_sha: str
|
|
162
|
+
) -> list[EnrichmentV2]:
|
|
163
|
+
"""Get architecture documentation enrichments for a commit."""
|
|
164
|
+
return await self.get_enrichments_for_commit(
|
|
165
|
+
commit_sha,
|
|
166
|
+
enrichment_type=ENRICHMENT_TYPE_ARCHITECTURE,
|
|
167
|
+
enrichment_subtype=ENRICHMENT_SUBTYPE_PHYSICAL,
|
|
168
|
+
)
|
|
81
169
|
|
|
82
|
-
|
|
83
|
-
|
|
170
|
+
async def get_api_docs_for_commit(self, commit_sha: str) -> list[EnrichmentV2]:
|
|
171
|
+
"""Get API documentation enrichments for a commit."""
|
|
172
|
+
return await self.get_enrichments_for_commit(
|
|
173
|
+
commit_sha,
|
|
174
|
+
enrichment_type=ENRICHMENT_TYPE_USAGE,
|
|
175
|
+
enrichment_subtype=ENRICHMENT_SUBTYPE_API_DOCS,
|
|
176
|
+
)
|
|
84
177
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
178
|
+
async def get_enrichment_entities_from_associations(
|
|
179
|
+
self, associations: list[EnrichmentAssociation]
|
|
180
|
+
) -> list[EnrichmentV2]:
|
|
181
|
+
"""Get enrichments by their associations."""
|
|
182
|
+
return await self.enrichment_repo.find(
|
|
183
|
+
EnrichmentQueryBuilder().for_ids(
|
|
184
|
+
enrichment_ids=[
|
|
185
|
+
int(association.entity_id) for association in associations
|
|
186
|
+
]
|
|
187
|
+
)
|
|
89
188
|
)
|
|
90
189
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
190
|
+
async def get_enrichments_by_ids(
|
|
191
|
+
self, enrichment_ids: list[int]
|
|
192
|
+
) -> list[EnrichmentV2]:
|
|
193
|
+
"""Get enrichments by their IDs."""
|
|
194
|
+
return await self.enrichment_repo.find(
|
|
195
|
+
EnrichmentQueryBuilder().for_ids(enrichment_ids=enrichment_ids)
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
async def has_snippets_for_commit(self, commit_sha: str) -> bool:
|
|
199
|
+
"""Check if a commit has snippet enrichments."""
|
|
200
|
+
snippets = await self.get_all_snippets_for_commit(commit_sha)
|
|
201
|
+
return len(snippets) > 0
|
|
202
|
+
|
|
203
|
+
async def has_summaries_for_commit(self, commit_sha: str) -> bool:
|
|
204
|
+
"""Check if a commit has summary enrichments."""
|
|
205
|
+
summaries = await self.get_summaries_for_commit(commit_sha)
|
|
206
|
+
return len(summaries) > 0
|
|
207
|
+
|
|
208
|
+
async def has_architecture_for_commit(self, commit_sha: str) -> bool:
|
|
209
|
+
"""Check if a commit has architecture enrichments."""
|
|
210
|
+
architecture_docs = await self.get_architecture_docs_for_commit(commit_sha)
|
|
211
|
+
return len(architecture_docs) > 0
|
|
212
|
+
|
|
213
|
+
async def has_api_docs_for_commit(self, commit_sha: str) -> bool:
|
|
214
|
+
"""Check if a commit has API documentation enrichments."""
|
|
215
|
+
api_docs = await self.get_api_docs_for_commit(commit_sha)
|
|
216
|
+
return len(api_docs) > 0
|
|
217
|
+
|
|
218
|
+
async def associations_for_enrichments(
|
|
219
|
+
self, enrichments: list[EnrichmentV2]
|
|
220
|
+
) -> list[EnrichmentAssociation]:
|
|
221
|
+
"""Get enrichment associations for given enrichment IDs."""
|
|
222
|
+
return await self.enrichment_association_repository.find(
|
|
223
|
+
EnrichmentAssociationQueryBuilder()
|
|
224
|
+
.for_enrichments(enrichments)
|
|
225
|
+
.for_enrichment_type()
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
async def snippet_associations_from_enrichments(
|
|
229
|
+
self, enrichments: list[EnrichmentV2]
|
|
230
|
+
) -> list[EnrichmentAssociation]:
|
|
231
|
+
"""Get snippet enrichment associations for given enrichments."""
|
|
232
|
+
return await self.enrichment_association_repository.find(
|
|
233
|
+
EnrichmentAssociationQueryBuilder()
|
|
234
|
+
.for_enrichments(enrichments)
|
|
235
|
+
.for_enrichment_type()
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
async def snippets_for_summary_enrichments(
|
|
239
|
+
self, summary_enrichments: list[EnrichmentV2]
|
|
240
|
+
) -> list[EnrichmentV2]:
|
|
241
|
+
"""Get snippet enrichment IDs for summary enrichments, preserving order."""
|
|
242
|
+
if not summary_enrichments:
|
|
243
|
+
return []
|
|
244
|
+
|
|
245
|
+
# Get associations where enrichment_id points to these summaries
|
|
246
|
+
associations = await self.enrichment_association_repository.find(
|
|
247
|
+
EnrichmentAssociationQueryBuilder()
|
|
248
|
+
.for_enrichments(summary_enrichments)
|
|
249
|
+
.for_enrichment_type()
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
all_enrichments = await self.enrichment_repo.find(
|
|
253
|
+
EnrichmentQueryBuilder().for_ids(
|
|
254
|
+
enrichment_ids=[
|
|
255
|
+
int(association.entity_id) for association in associations
|
|
256
|
+
]
|
|
257
|
+
)
|
|
258
|
+
)
|
|
259
|
+
snippet_enrichments = [
|
|
260
|
+
e for e in all_enrichments if e.subtype == ENRICHMENT_SUBTYPE_SNIPPET
|
|
261
|
+
]
|
|
262
|
+
|
|
263
|
+
# Re-Sort snippet enrichments to be in the same order as the associations
|
|
264
|
+
original_snippet_ids = [association.entity_id for association in associations]
|
|
265
|
+
return sorted(
|
|
266
|
+
snippet_enrichments,
|
|
267
|
+
key=lambda x: original_snippet_ids.index(str(x.id)),
|
|
268
|
+
)
|
|
269
|
+
|
|
270
|
+
async def get_enrichments_pointing_to_enrichments(
|
|
271
|
+
self, target_enrichment_ids: list[int]
|
|
272
|
+
) -> dict[int, list[EnrichmentV2]]:
|
|
273
|
+
"""Get enrichments that point to the given enrichments, grouped by target."""
|
|
274
|
+
# Get associations pointing to these enrichments
|
|
275
|
+
associations = await self.enrichment_association_repository.find(
|
|
276
|
+
EnrichmentAssociationQueryBuilder()
|
|
277
|
+
.for_enrichment_type()
|
|
278
|
+
.for_entity_ids(
|
|
279
|
+
[str(enrichment_id) for enrichment_id in target_enrichment_ids]
|
|
280
|
+
)
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
if not associations:
|
|
284
|
+
return {eid: [] for eid in target_enrichment_ids}
|
|
285
|
+
|
|
286
|
+
# Get the enrichments referenced by these associations
|
|
287
|
+
enrichment_ids = [a.enrichment_id for a in associations]
|
|
288
|
+
enrichments = await self.enrichment_repo.find(
|
|
289
|
+
EnrichmentQueryBuilder().for_ids(enrichment_ids=enrichment_ids)
|
|
290
|
+
)
|
|
291
|
+
|
|
292
|
+
# Create lookup map
|
|
293
|
+
enrichment_map = {e.id: e for e in enrichments if e.id is not None}
|
|
294
|
+
|
|
295
|
+
# Group by target enrichment ID
|
|
296
|
+
result: dict[int, list[EnrichmentV2]] = {
|
|
297
|
+
eid: [] for eid in target_enrichment_ids
|
|
298
|
+
}
|
|
299
|
+
for association in associations:
|
|
300
|
+
target_id = int(association.entity_id)
|
|
301
|
+
if target_id in result and association.enrichment_id in enrichment_map:
|
|
302
|
+
result[target_id].append(enrichment_map[association.enrichment_id])
|
|
303
|
+
|
|
304
|
+
return result
|
|
305
|
+
|
|
306
|
+
async def summary_to_snippet_map(self, summary_ids: list[int]) -> dict[int, int]:
|
|
307
|
+
"""Get a map of summary IDs to snippet IDs."""
|
|
308
|
+
# Get the snippet enrichment IDs that these summaries point to
|
|
309
|
+
summary_enrichments = await self.get_enrichments_by_ids(summary_ids)
|
|
310
|
+
|
|
311
|
+
# Get all the associations for these summary enrichments
|
|
312
|
+
all_associations = await self.associations_for_enrichments(summary_enrichments)
|
|
313
|
+
|
|
314
|
+
# Get all enrichments for these summary associations
|
|
315
|
+
all_snippet_enrichments = await self.get_enrichment_entities_from_associations(
|
|
316
|
+
all_associations
|
|
317
|
+
)
|
|
318
|
+
snippet_type_map = {e.id: e.subtype for e in all_snippet_enrichments}
|
|
94
319
|
|
|
95
|
-
|
|
320
|
+
# Create a lookup map from summary ID to snippet ID, via the associations,
|
|
321
|
+
# filtering out any snippets that are not summary enrichments
|
|
322
|
+
return {
|
|
323
|
+
assoc.enrichment_id: int(assoc.entity_id)
|
|
324
|
+
for assoc in all_associations
|
|
325
|
+
if snippet_type_map[int(assoc.entity_id)] == ENRICHMENT_SUBTYPE_SNIPPET
|
|
326
|
+
}
|
|
@@ -75,7 +75,7 @@ class IndexingWorkerService:
|
|
|
75
75
|
if task:
|
|
76
76
|
await self._process_task(task)
|
|
77
77
|
# Only remove the task if it was processed successfully
|
|
78
|
-
await self.task_repository.
|
|
78
|
+
await self.task_repository.delete(task)
|
|
79
79
|
continue
|
|
80
80
|
|
|
81
81
|
# If no task, sleep for a bit
|
|
@@ -8,6 +8,7 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
8
8
|
|
|
9
9
|
from kodit.domain.entities import Task
|
|
10
10
|
from kodit.domain.value_objects import QueuePriority, TaskOperation
|
|
11
|
+
from kodit.infrastructure.sqlalchemy.query import FilterOperator, QueryBuilder
|
|
11
12
|
from kodit.infrastructure.sqlalchemy.task_repository import (
|
|
12
13
|
create_task_repository,
|
|
13
14
|
)
|
|
@@ -30,16 +31,12 @@ class QueueService:
|
|
|
30
31
|
|
|
31
32
|
async def enqueue_task(self, task: Task) -> None:
|
|
32
33
|
"""Queue a task in the database."""
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
db_task.priority = task.priority
|
|
38
|
-
await self.task_repository.update(db_task)
|
|
34
|
+
# Check if task already exists
|
|
35
|
+
exists = await self.task_repository.exists(task.id)
|
|
36
|
+
await self.task_repository.save(task)
|
|
37
|
+
if exists:
|
|
39
38
|
self.log.info("Task updated", task_id=task.id, task_type=task.type)
|
|
40
39
|
else:
|
|
41
|
-
# Otherwise, add task
|
|
42
|
-
await self.task_repository.add(task)
|
|
43
40
|
self.log.info(
|
|
44
41
|
"Task queued",
|
|
45
42
|
task_id=task.id,
|
|
@@ -69,8 +66,16 @@ class QueueService:
|
|
|
69
66
|
self, task_operation: TaskOperation | None = None
|
|
70
67
|
) -> list[Task]:
|
|
71
68
|
"""List all tasks in the queue."""
|
|
72
|
-
|
|
69
|
+
query = QueryBuilder()
|
|
70
|
+
if task_operation:
|
|
71
|
+
query.filter("type", FilterOperator.EQ, task_operation.value)
|
|
72
|
+
query.sort("priority", descending=True)
|
|
73
|
+
query.sort("created_at", descending=True)
|
|
74
|
+
return await self.task_repository.find(query)
|
|
73
75
|
|
|
74
76
|
async def get_task(self, task_id: str) -> Task | None:
|
|
75
77
|
"""Get a specific task by ID."""
|
|
76
|
-
|
|
78
|
+
try:
|
|
79
|
+
return await self.task_repository.get(task_id)
|
|
80
|
+
except ValueError:
|
|
81
|
+
return None
|
|
@@ -11,6 +11,7 @@ from kodit.domain.value_objects import (
|
|
|
11
11
|
PrescribedOperations,
|
|
12
12
|
QueuePriority,
|
|
13
13
|
)
|
|
14
|
+
from kodit.infrastructure.sqlalchemy.query import QueryBuilder
|
|
14
15
|
|
|
15
16
|
|
|
16
17
|
class SyncSchedulerService:
|
|
@@ -68,7 +69,7 @@ class SyncSchedulerService:
|
|
|
68
69
|
self.log.info("Starting sync operation")
|
|
69
70
|
|
|
70
71
|
# Sync each index - queue all 5 tasks with priority ordering
|
|
71
|
-
for repo in await self.repo_repository.
|
|
72
|
+
for repo in await self.repo_repository.find(QueryBuilder()):
|
|
72
73
|
await self.queue_service.enqueue_tasks(
|
|
73
74
|
tasks=PrescribedOperations.SYNC_REPOSITORY,
|
|
74
75
|
base_priority=QueuePriority.BACKGROUND,
|
|
@@ -10,7 +10,7 @@ from kodit.domain.enrichments.enrichment import (
|
|
|
10
10
|
ENRICHMENT_TYPE_ARCHITECTURE = "architecture"
|
|
11
11
|
|
|
12
12
|
|
|
13
|
-
@dataclass
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
14
|
class ArchitectureEnrichment(CommitEnrichment, ABC):
|
|
15
15
|
"""Enrichment containing physical architecture discovery for a commit."""
|
|
16
16
|
|
|
@@ -7,7 +7,7 @@ from kodit.domain.enrichments.architecture.architecture import ArchitectureEnric
|
|
|
7
7
|
ENRICHMENT_SUBTYPE_PHYSICAL = "physical"
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
@dataclass
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
11
|
class PhysicalArchitectureEnrichment(ArchitectureEnrichment):
|
|
12
12
|
"""Enrichment containing physical architecture discovery for a commit."""
|
|
13
13
|
|
|
@@ -8,7 +8,7 @@ from kodit.domain.enrichments.enrichment import CommitEnrichment
|
|
|
8
8
|
ENRICHMENT_TYPE_DEVELOPMENT = "development"
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
@dataclass
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
12
|
class DevelopmentEnrichment(CommitEnrichment, ABC):
|
|
13
13
|
"""Enrichment containing development discovery for a commit."""
|
|
14
14
|
|
|
@@ -5,10 +5,11 @@ from dataclasses import dataclass
|
|
|
5
5
|
from kodit.domain.enrichments.development.development import DevelopmentEnrichment
|
|
6
6
|
|
|
7
7
|
ENRICHMENT_SUBTYPE_SNIPPET_SUMMARY = "snippet_summary"
|
|
8
|
+
ENRICHMENT_SUBTYPE_SNIPPET = "snippet"
|
|
8
9
|
|
|
9
10
|
|
|
10
|
-
@dataclass
|
|
11
|
-
class
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class SnippetEnrichmentSummary(DevelopmentEnrichment):
|
|
12
13
|
"""Enrichment specific to code snippets."""
|
|
13
14
|
|
|
14
15
|
@property
|
|
@@ -16,6 +17,12 @@ class SnippetEnrichment(DevelopmentEnrichment):
|
|
|
16
17
|
"""Return the enrichment subtype."""
|
|
17
18
|
return ENRICHMENT_SUBTYPE_SNIPPET_SUMMARY
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
|
|
21
|
+
@dataclass(frozen=True)
|
|
22
|
+
class SnippetEnrichment(DevelopmentEnrichment):
|
|
23
|
+
"""Enrichment specific to code snippets."""
|
|
24
|
+
|
|
25
|
+
@property
|
|
26
|
+
def subtype(self) -> str | None:
|
|
27
|
+
"""Return the enrichment subtype."""
|
|
28
|
+
return ENRICHMENT_SUBTYPE_SNIPPET
|
|
@@ -4,12 +4,14 @@ from abc import ABC, abstractmethod
|
|
|
4
4
|
from dataclasses import dataclass
|
|
5
5
|
from datetime import datetime
|
|
6
6
|
|
|
7
|
+
# TODO(Phil): db stuff should not exist in the domain layer, create a mapper for this.
|
|
8
|
+
from kodit.infrastructure.sqlalchemy import entities as db_entities
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
9
12
|
class EnrichmentV2(ABC):
|
|
10
13
|
"""Generic enrichment that can be attached to any entity."""
|
|
11
14
|
|
|
12
|
-
entity_id: str
|
|
13
15
|
content: str = ""
|
|
14
16
|
id: int | None = None
|
|
15
17
|
created_at: datetime | None = None
|
|
@@ -30,10 +32,35 @@ class EnrichmentV2(ABC):
|
|
|
30
32
|
"""Return the entity type key this enrichment is for."""
|
|
31
33
|
|
|
32
34
|
|
|
33
|
-
@dataclass
|
|
35
|
+
@dataclass(frozen=True)
|
|
34
36
|
class CommitEnrichment(EnrichmentV2, ABC):
|
|
35
37
|
"""Enrichment specific to commits."""
|
|
36
38
|
|
|
37
39
|
def entity_type_key(self) -> str:
|
|
38
40
|
"""Return the entity type key this enrichment is for."""
|
|
39
|
-
return
|
|
41
|
+
return db_entities.GitCommit.__tablename__
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
@dataclass(frozen=True)
|
|
45
|
+
class EnrichmentAssociation:
|
|
46
|
+
"""Association between an enrichment and an entity."""
|
|
47
|
+
|
|
48
|
+
enrichment_id: int
|
|
49
|
+
entity_id: str
|
|
50
|
+
entity_type: str
|
|
51
|
+
id: int | None = None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
@dataclass(frozen=True)
|
|
55
|
+
class CommitEnrichmentAssociation(EnrichmentAssociation):
|
|
56
|
+
"""Association between a commit and an enrichment."""
|
|
57
|
+
|
|
58
|
+
entity_type: str = db_entities.GitCommit.__tablename__
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@dataclass
|
|
62
|
+
class SnippetSummaryAssociation:
|
|
63
|
+
"""Association between a snippet and a summary enrichment."""
|
|
64
|
+
|
|
65
|
+
snippet_summary: EnrichmentAssociation
|
|
66
|
+
snippet: EnrichmentAssociation
|