diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 83cb14b..e3c952c 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -21,6 +21,7 @@ jobs: with: working-directory: web cache-dependency-path: web/package-lock.json + node-version: "24" run-cdk-synth: false run-conventions-check: false @@ -38,6 +39,7 @@ jobs: with: working-directory: mobile cache-dependency-path: mobile/package-lock.json + node-version: "24" run-cdk-synth: false run-conventions-check: false @@ -47,6 +49,7 @@ jobs: with: working-directory: infra cache-dependency-path: infra/package-lock.json + node-version: "24" dotnet-version: "8.0.x" dotnet-publish-project: api/src/ProposalSystem.Api/ProposalSystem.Api.csproj run-typecheck: false diff --git a/infra/lib/compute-stack.ts b/infra/lib/compute-stack.ts index 2f4a186..98e624e 100644 --- a/infra/lib/compute-stack.ts +++ b/infra/lib/compute-stack.ts @@ -93,7 +93,9 @@ export class ComputeStack extends cdk.Stack { // Lambda to pre-create the vector index (retries until AOSS access policy propagates) const indexCreatorFn = new lambda.Function(this, 'OssIndexCreator', { + functionName: 'proposal-system-oss-index-creator', runtime: lambda.Runtime.PYTHON_3_12, + architecture: lambda.Architecture.ARM_64, handler: 'app.handler', code: lambda.Code.fromAsset('../lambdas/oss-index-creator', { bundling: { @@ -105,6 +107,7 @@ export class ComputeStack extends cdk.Stack { }, }), timeout: cdk.Duration.minutes(6), + logRetention: logs.RetentionDays.TWO_MONTHS, }); indexCreatorFn.addToRolePolicy(new iam.PolicyStatement({ diff --git a/infra/lib/foundation-stack.ts b/infra/lib/foundation-stack.ts index 4040621..4285768 100644 --- a/infra/lib/foundation-stack.ts +++ b/infra/lib/foundation-stack.ts @@ -259,6 +259,7 @@ export class FoundationStack extends cdk.Stack { 'proposal-system-pdf-extract', 'proposal-system-pdf-generate', 'proposal-system-library-ingest', + 'proposal-system-suggestions', ]; for (const name of logGroupNames) { diff --git a/lambdas/library-ingest/app.py b/lambdas/library-ingest/app.py index c1de57e..eca3195 100644 --- a/lambdas/library-ingest/app.py +++ b/lambdas/library-ingest/app.py @@ -8,7 +8,6 @@ then triggers a KB sync. import json import logging import os -import time from datetime import datetime import boto3 @@ -199,27 +198,3 @@ def _api_headers() -> dict: if api_key: headers["X-Internal-Api-Key"] = api_key return headers - - -def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response: - kwargs.setdefault("headers", _api_headers()) - kwargs.setdefault("timeout", 10) - for attempt in range(retries): - try: - resp = httpx.request(method, url, **kwargs) - if resp.status_code < 500: - return resp - logger.warning( - "API returned %s on attempt %d for %s", - resp.status_code, - attempt + 1, - url, - ) - except httpx.TransportError as e: - logger.warning( - "Transport error on attempt %d for %s: %s", attempt + 1, url, e - ) - if attempt == retries - 1: - raise - time.sleep(min(2**attempt, 4)) - return resp # type: ignore[possibly-undefined] diff --git a/lambdas/oss-index-creator/app.py b/lambdas/oss-index-creator/app.py index 23dc6e8..e6233c9 100644 --- a/lambdas/oss-index-creator/app.py +++ b/lambdas/oss-index-creator/app.py @@ -37,9 +37,7 @@ def handler(event, context): ) index_body = { - "settings": { - "index": {"knn": True, "knn.algo_param.ef_search": 512} - }, + "settings": {"index": {"knn": True, "knn.algo_param.ef_search": 512}}, "mappings": { "properties": { vector_field: { diff --git a/lambdas/pdf-extract/app.py b/lambdas/pdf-extract/app.py index 9f35aef..f1bc293 100644 --- a/lambdas/pdf-extract/app.py +++ b/lambdas/pdf-extract/app.py @@ -9,7 +9,6 @@ import json import logging import os import tempfile -import time import boto3 import httpx @@ -339,27 +338,3 @@ def _api_headers() -> dict: if api_key: headers["X-Internal-Api-Key"] = api_key return headers - - -def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response: - kwargs.setdefault("headers", _api_headers()) - kwargs.setdefault("timeout", 10) - for attempt in range(retries): - try: - resp = httpx.request(method, url, **kwargs) - if resp.status_code < 500: - return resp - logger.warning( - "API returned %s on attempt %d for %s", - resp.status_code, - attempt + 1, - url, - ) - except httpx.TransportError as e: - logger.warning( - "Transport error on attempt %d for %s: %s", attempt + 1, url, e - ) - if attempt == retries - 1: - raise - time.sleep(min(2**attempt, 4)) - return resp # type: ignore[possibly-undefined] diff --git a/lambdas/pdf-generate/app.py b/lambdas/pdf-generate/app.py index f188cc8..37e75db 100644 --- a/lambdas/pdf-generate/app.py +++ b/lambdas/pdf-generate/app.py @@ -7,7 +7,6 @@ Triggered via SQS when an admin requests PDF generation. import json import logging import os -import time from datetime import datetime from io import BytesIO @@ -543,27 +542,3 @@ def _api_headers() -> dict: if api_key: headers["X-Internal-Api-Key"] = api_key return headers - - -def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response: - kwargs.setdefault("headers", _api_headers()) - kwargs.setdefault("timeout", 10) - for attempt in range(retries): - try: - resp = httpx.request(method, url, **kwargs) - if resp.status_code < 500: - return resp - logger.warning( - "API returned %s on attempt %d for %s", - resp.status_code, - attempt + 1, - url, - ) - except httpx.TransportError as e: - logger.warning( - "Transport error on attempt %d for %s: %s", attempt + 1, url, e - ) - if attempt == retries - 1: - raise - time.sleep(min(2**attempt, 4)) - return resp # type: ignore[possibly-undefined] diff --git a/lambdas/suggestions/app.py b/lambdas/suggestions/app.py index d9a9f6e..9e68f83 100644 --- a/lambdas/suggestions/app.py +++ b/lambdas/suggestions/app.py @@ -7,7 +7,6 @@ to generate line item suggestions for new proposals. import json import logging import os -import time import boto3 import httpx @@ -320,27 +319,3 @@ def _api_headers() -> dict: if api_key: headers["X-Internal-Api-Key"] = api_key return headers - - -def _api_request(method: str, url: str, retries: int = 3, **kwargs) -> httpx.Response: - kwargs.setdefault("headers", _api_headers()) - kwargs.setdefault("timeout", 10) - for attempt in range(retries): - try: - resp = httpx.request(method, url, **kwargs) - if resp.status_code < 500: - return resp - logger.warning( - "API returned %s on attempt %d for %s", - resp.status_code, - attempt + 1, - url, - ) - except httpx.TransportError as e: - logger.warning( - "Transport error on attempt %d for %s: %s", attempt + 1, url, e - ) - if attempt == retries - 1: - raise - time.sleep(min(2**attempt, 4)) - return resp # type: ignore[possibly-undefined]