|
1 | | -from fastapi import Depends |
2 | | -from fastapi.responses import JSONResponse |
| 1 | +import json |
| 2 | +import logging |
| 3 | +import uuid |
| 4 | +from datetime import ( |
| 5 | + UTC, |
| 6 | + datetime, |
| 7 | +) |
| 8 | + |
| 9 | +import aioboto3 |
| 10 | +from botocore.exceptions import ClientError |
| 11 | +from fastapi import ( |
| 12 | + Depends, |
| 13 | + HTTPException, |
| 14 | +) |
3 | 15 | from sqlalchemy.ext.asyncio import AsyncSession |
4 | 16 |
|
5 | 17 | from fai.app import fai_app |
|
9 | 21 | verify_token, |
10 | 22 | ) |
11 | 23 | from fai.models.api.github_source_api import ( |
12 | | - GithubIndexStatusResponse, |
13 | 24 | IndexGithubRequest, |
14 | 25 | IndexGithubResponse, |
15 | | - ReindexGithubRequest, |
16 | | - ReindexGithubResponse, |
17 | 26 | ) |
| 27 | +from fai.models.db.index_source_db import ( |
| 28 | + IndexSourceDb, |
| 29 | + IndexSourceStatus, |
| 30 | + SourceType, |
| 31 | +) |
| 32 | + |
| 33 | +logger = logging.getLogger(__name__) |
| 34 | + |
| 35 | +LAMBDA_FUNCTION_NAME = "fai-code-indexing-dev2" |
18 | 36 |
|
19 | 37 |
|
20 | 38 | @fai_app.post( |
|
23 | 41 | dependencies=[Depends(verify_token)], |
24 | 42 | openapi_extra={"x-fern-audiences": ["internal"]}, |
25 | 43 | ) |
26 | | -async def index_github_source( |
| 44 | +async def index_github_source_repos( |
27 | 45 | domain: str, |
28 | 46 | request: IndexGithubRequest, |
29 | 47 | db: AsyncSession = Depends(get_db), |
30 | | -) -> JSONResponse: |
| 48 | +) -> IndexGithubResponse: |
31 | 49 | """Start indexing a GitHub repository for a domain.""" |
32 | | - strip_domain(domain) |
| 50 | + stripped_domain = strip_domain(domain) |
33 | 51 |
|
34 | | - # TODO: Implement GitHub indexing logic |
35 | | - # - Create IndexSourceDb record |
36 | | - # - Start background indexing job |
37 | | - # - Return job_id and repo_url |
| 52 | + job_id = str(uuid.uuid4()) |
38 | 53 |
|
39 | | - raise NotImplementedError("GitHub indexing not yet implemented") |
| 54 | + now = datetime.now(UTC) |
| 55 | + for repo_url in request.repo_urls: |
| 56 | + index_source = IndexSourceDb( |
| 57 | + id=str(uuid.uuid4()), |
| 58 | + domain=stripped_domain, |
| 59 | + source_type=SourceType.GITHUB, |
| 60 | + source_identifier=repo_url, |
| 61 | + config={}, |
| 62 | + job_id=job_id, |
| 63 | + status=IndexSourceStatus.INDEXING, |
| 64 | + metrics={}, |
| 65 | + created_at=now, |
| 66 | + updated_at=now, |
| 67 | + ) |
| 68 | + db.add(index_source) |
40 | 69 |
|
| 70 | + await db.commit() |
41 | 71 |
|
42 | | -@fai_app.get( |
43 | | - "/sources/github/{domain}/status", |
44 | | - response_model=GithubIndexStatusResponse, |
45 | | - dependencies=[Depends(verify_token)], |
46 | | - openapi_extra={"x-fern-audiences": ["internal"]}, |
47 | | -) |
48 | | -async def get_github_index_status( |
49 | | - domain: str, |
50 | | - db: AsyncSession = Depends(get_db), |
51 | | -) -> JSONResponse: |
52 | | - """Get the indexing status for a GitHub repository.""" |
53 | | - strip_domain(domain) |
54 | | - |
55 | | - # TODO: Implement status check logic |
56 | | - # - Query IndexSourceDb for the domain |
57 | | - # - Return current status and metrics |
58 | | - |
59 | | - raise NotImplementedError("GitHub status check not yet implemented") |
| 72 | + try: |
| 73 | + session = aioboto3.Session() |
| 74 | + async with session.client("lambda") as lambda_client: |
| 75 | + payload = { |
| 76 | + "domain": stripped_domain, |
| 77 | + "eventType": "indexRepo", |
| 78 | + "repoUrls": request.repo_urls, |
| 79 | + } |
60 | 80 |
|
| 81 | + response = await lambda_client.invoke( |
| 82 | + FunctionName=LAMBDA_FUNCTION_NAME, |
| 83 | + InvocationType="Event", |
| 84 | + Payload=json.dumps(payload), |
| 85 | + ) |
61 | 86 |
|
62 | | -@fai_app.post( |
63 | | - "/sources/github/{domain}/reindex", |
64 | | - response_model=ReindexGithubResponse, |
65 | | - dependencies=[Depends(verify_token)], |
66 | | - openapi_extra={"x-fern-audiences": ["internal"]}, |
67 | | -) |
68 | | -async def reindex_github_source( |
69 | | - domain: str, |
70 | | - request: ReindexGithubRequest, |
71 | | - db: AsyncSession = Depends(get_db), |
72 | | -) -> JSONResponse: |
73 | | - """Delete existing index and start a new indexing job for a GitHub repository.""" |
74 | | - strip_domain(domain) |
| 87 | + logger.info( |
| 88 | + f"Successfully invoked code indexing Lambda. " |
| 89 | + f"StatusCode: {response.get('StatusCode')}, " |
| 90 | + f"Domain: {stripped_domain}, " |
| 91 | + f"RepoUrls: {request.repo_urls}, " |
| 92 | + f"JobId: {job_id}" |
| 93 | + ) |
75 | 94 |
|
76 | | - # TODO: Implement reindexing logic |
77 | | - # - Delete old IndexSourceDb records and indexed content |
78 | | - # - Create new IndexSourceDb record |
79 | | - # - Start new background indexing job |
80 | | - # - Return new job_id |
| 95 | + except ClientError as e: |
| 96 | + logger.error( |
| 97 | + f"Failed to invoke code indexing Lambda: {e.response['Error']['Code']} - {e.response['Error']['Message']}", |
| 98 | + exc_info=True, |
| 99 | + ) |
| 100 | + raise HTTPException(status_code=500, detail="Failed to start indexing job") |
| 101 | + except Exception as e: |
| 102 | + logger.error(f"Unexpected error invoking code indexing Lambda: {str(e)}", exc_info=True) |
| 103 | + raise HTTPException(status_code=500, detail="Failed to start indexing job") |
81 | 104 |
|
82 | | - raise NotImplementedError("GitHub reindexing not yet implemented") |
| 105 | + return IndexGithubResponse(job_id=job_id, repo_urls=request.repo_urls) |
0 commit comments