From af35ae315e8843dbb2c617e789d983b92627fe88 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 26 Sep 2023 19:34:50 -0300 Subject: [PATCH 1/4] =?UTF-8?q?=F0=9F=93=9D=20docs(async-api.mdx):=20updat?= =?UTF-8?q?e=20endpoint=20path=20for=20checking=20task=20status=20to=20imp?= =?UTF-8?q?rove=20consistency=20and=20clarity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🐛 fix(endpoints.py): update endpoint path for checking task status to match the updated path in the documentation 🐛 fix(schemas.py): add TaskResponse schema to properly handle task response data 🐛 fix(locustfile.py): update endpoint path for polling task status to match the updated path in the endpoints 🐛 fix(test_endpoints.py): update helper function and test cases to use the new task response structure and endpoint path for polling task status --- docs/docs/guidelines/async-api.mdx | 4 ++-- src/backend/langflow/api/v1/endpoints.py | 11 +++++++++-- src/backend/langflow/api/v1/schemas.py | 9 ++++++++- tests/locust/locustfile.py | 2 +- tests/test_endpoints.py | 20 ++++++++++++++------ 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/docs/docs/guidelines/async-api.mdx b/docs/docs/guidelines/async-api.mdx index 582a5e1c8..9ef836704 100644 --- a/docs/docs/guidelines/async-api.mdx +++ b/docs/docs/guidelines/async-api.mdx @@ -29,11 +29,11 @@ curl -X POST \ ## Checking Task Status -You can check the status of an asynchronous task by making a GET request to the `/task/{task_id}/status` endpoint. +You can check the status of an asynchronous task by making a GET request to the `/task/{task_id}` endpoint. ```bash curl -X GET \ - http://localhost:3000/api/v1/task//status \ + http://localhost:3000/api/v1/task/ \ -H 'x-api-key: ' ``` diff --git a/src/backend/langflow/api/v1/endpoints.py b/src/backend/langflow/api/v1/endpoints.py index ff5e0541e..864467f9b 100644 --- a/src/backend/langflow/api/v1/endpoints.py +++ b/src/backend/langflow/api/v1/endpoints.py @@ -20,6 +20,7 @@ from langflow.interface.custom.custom_component import CustomComponent from langflow.api.v1.schemas import ( ProcessResponse, + TaskResponse, TaskStatusResponse, UploadFileResponse, CustomComponentCode, @@ -145,9 +146,15 @@ async def process_flow( session_id, ) task_result = task.status + + if task_id: + task_response = TaskResponse(id=task_id, href=f"api/v1/task/{task_id}") + else: + task_response = None + return ProcessResponse( result=task_result, - id=task_id, + task=task_response, session_id=session_id, backend=str(type(task_service.backend)), ) @@ -173,7 +180,7 @@ async def process_flow( raise HTTPException(status_code=500, detail=str(e)) from e -@router.get("/task/{task_id}/status", response_model=TaskStatusResponse) +@router.get("/task/{task_id}", response_model=TaskStatusResponse) async def get_task_status(task_id: str): task_service = get_task_service() task = task_service.get_task(task_id) diff --git a/src/backend/langflow/api/v1/schemas.py b/src/backend/langflow/api/v1/schemas.py index 519bc534e..9c6ac6d60 100644 --- a/src/backend/langflow/api/v1/schemas.py +++ b/src/backend/langflow/api/v1/schemas.py @@ -47,11 +47,18 @@ class UpdateTemplateRequest(BaseModel): template: dict +class TaskResponse(BaseModel): + """Task response schema.""" + + id: Optional[str] = Field(None) + href: Optional[str] = Field(None) + + class ProcessResponse(BaseModel): """Process response schema.""" result: Any - id: Optional[str] = None + task: Optional[TaskResponse] = None session_id: Optional[str] = None backend: Optional[str] = None diff --git a/tests/locust/locustfile.py b/tests/locust/locustfile.py index 000c3456d..aca0d1de9 100644 --- a/tests/locust/locustfile.py +++ b/tests/locust/locustfile.py @@ -19,7 +19,7 @@ class NameTest(FastHttpUser): while True: with self.rest( "GET", - f"/task/{task_id}/status", + f"/task/{task_id}", name="task_status", headers=self.headers, ) as response: diff --git a/tests/test_endpoints.py b/tests/test_endpoints.py index 43a68580a..1de7c9deb 100644 --- a/tests/test_endpoints.py +++ b/tests/test_endpoints.py @@ -25,10 +25,10 @@ def run_post(client, flow_id, headers, post_data): # Helper function to poll task status -def poll_task_status(client, headers, task_id, max_attempts=20, sleep_time=1): +def poll_task_status(client, headers, href, max_attempts=20, sleep_time=1): for _ in range(max_attempts): task_status_response = client.get( - f"api/v1/task/{task_id}/status", + href, headers=headers, ) if ( @@ -544,11 +544,15 @@ def test_async_task_processing(distributed_client, added_flow, created_api_key): assert response.status_code == 200, response.json() # Extract the task ID from the response - task_id = response.json().get("id") + task = response.json().get("task") + task_id = task.get("id") + task_href = task.get("href") assert task_id is not None + assert task_href is not None + assert task_href == f"api/v1/task/{task_id}" # Polling the task status using the helper function - task_status_json = poll_task_status(distributed_client, headers, task_id) + task_status_json = poll_task_status(distributed_client, headers, task_href) assert task_status_json is not None, "Task did not complete in time" # Validate that the task completed successfully and the result is as expected @@ -576,11 +580,15 @@ def test_async_task_processing_vector_store( assert "FAILURE" not in response.json()["result"] # Extract the task ID from the response - task_id = response.json().get("id") + task = response.json().get("task") + task_id = task.get("id") + task_href = task.get("href") assert task_id is not None + assert task_href is not None + assert task_href == f"api/v1/task/{task_id}" # Polling the task status using the helper function - task_status_json = poll_task_status(client, headers, task_id, max_attempts=40) + task_status_json = poll_task_status(client, headers, task_href) assert task_status_json is not None, "Task did not complete in time" # Validate that the task completed successfully and the result is as expected From 868515958e2e60d6e714a0086bb4eb89ece5fc58 Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 26 Sep 2023 19:45:08 -0300 Subject: [PATCH 2/4] =?UTF-8?q?=F0=9F=93=9D=20docs(async-api.mdx):=20add?= =?UTF-8?q?=20response=20example=20for=20async=20API=20request=20to=20impr?= =?UTF-8?q?ove=20documentation=20clarity?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/docs/guidelines/async-api.mdx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/docs/guidelines/async-api.mdx b/docs/docs/guidelines/async-api.mdx index 9ef836704..c5473812e 100644 --- a/docs/docs/guidelines/async-api.mdx +++ b/docs/docs/guidelines/async-api.mdx @@ -27,6 +27,22 @@ curl -X POST \ -d '{"inputs": {"text": ""}, "tweaks": {}, "sync": false}' ``` +Response: + +```json +{ + "result": { + "output": "..." + }, + "task": { + "id": "...", + "href": "api/v1/task/" + }, + "session_id": "...", + "backend": "..." // celery or anyio +} +``` + ## Checking Task Status You can check the status of an asynchronous task by making a GET request to the `/task/{task_id}` endpoint. From f506fd16253e96fbb5cb144881573fcceb5e86bb Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 26 Sep 2023 19:58:50 -0300 Subject: [PATCH 3/4] =?UTF-8?q?=F0=9F=94=A5=20chore(deploy):=20remove=20un?= =?UTF-8?q?used=20docker-compose.test.yml=20file=20=F0=9F=94=A7=20chore(de?= =?UTF-8?q?ploy):=20update=20docker-compose.override.yml=20to=20version=20?= =?UTF-8?q?3.8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 📦 chore(docker-compose.with_tests.yml): add docker-compose file with tests configuration This commit adds a new docker-compose file named `docker-compose.with_tests.yml` which includes the configuration for running tests. The file includes the following services: - `proxy`: Configures Traefik as a reverse proxy with Docker integration and enables access logs, the Traefik dashboard, and API. - `backend`: Sets up the backend service with dependencies on a database, message broker, and result backend. It also includes labels for Traefik routing. - `db`: Configures a PostgreSQL database with a volume for data persistence. - `pgadmin`: Sets up pgAdmin for managing the PostgreSQL database. - `result_backend`: Configures a Redis instance for the result backend. - `celeryworker`: Sets up a Celery worker for background task processing. - `flower`: Configures Flower for monitoring and managing Celery workers. - `frontend`: Sets up the frontend service with labels for Traefik routing. - `broker`: Configures RabbitMQ with the management console. - `prometheus`: Sets up Prometheus for monitoring. - `grafana`: Configures Grafana for visualization and monitoring. - `tests`: Extends the `backend` service and runs pytest for running tests. This file allows running the application with the necessary services for testing and monitoring. 🔧 chore(docker-compose.yml): add missing volumes and networks for services 🔧 chore(docker-compose.yml): add traefik-public network with configurable external setting for flexibility in testing 📝 docs(async-tasks.mdx): update docker-compose command to use the correct file name for running tests --- deploy/docker-compose.override.yml | 1 + deploy/docker-compose.test.yml | 85 -------- deploy/docker-compose.with_tests.yml | 277 +++++++++++++++++++++++++++ docs/docs/guides/async-tasks.mdx | 2 +- 4 files changed, 279 insertions(+), 86 deletions(-) delete mode 100644 deploy/docker-compose.test.yml create mode 100644 deploy/docker-compose.with_tests.yml diff --git a/deploy/docker-compose.override.yml b/deploy/docker-compose.override.yml index e5c0d9dd7..1992916fb 100644 --- a/deploy/docker-compose.override.yml +++ b/deploy/docker-compose.override.yml @@ -1,4 +1,5 @@ version: "3.8" + services: proxy: ports: diff --git a/deploy/docker-compose.test.yml b/deploy/docker-compose.test.yml deleted file mode 100644 index 829aae883..000000000 --- a/deploy/docker-compose.test.yml +++ /dev/null @@ -1,85 +0,0 @@ -version: "3.8" -services: - proxy: - ports: - - "80:80" - - "8090:8080" - command: - # Enable Docker in Traefik, so that it reads labels from Docker services - - --providers.docker - # Add a constraint to only use services with the label for this stack - # from the env var TRAEFIK_TAG - - --providers.docker.constraints=Label(`traefik.constraint-label-stack`, `${TRAEFIK_TAG?Variable not set}`) - # Do not expose all Docker services, only the ones explicitly exposed - - --providers.docker.exposedbydefault=false - # Disable Docker Swarm mode for local development - # - --providers.docker.swarmmode - # Enable the access log, with HTTP requests - - --accesslog - # Enable the Traefik log, for configurations and errors - - --log - # Enable the Dashboard and API - - --api - # Enable the Dashboard and API in insecure mode for local development - - --api.insecure=true - labels: - - traefik.enable=true - - traefik.http.routers.${STACK_NAME?Variable not set}-traefik-public-http.rule=Host(`${DOMAIN?Variable not set}`) - - traefik.http.services.${STACK_NAME?Variable not set}-traefik-public.loadbalancer.server.port=80 - - result_backend: - ports: - - "6379:6379" - - pgadmin: - ports: - - "5050:5050" - - flower: - ports: - - "5555:5555" - - backend: - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`) - - traefik.http.services.${STACK_NAME?Variable not set}-backend.loadbalancer.server.port=7860 - - frontend: - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`) - - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 - - celeryworker: - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-celeryworker-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`) - - traefik.http.services.${STACK_NAME?Variable not set}-celeryworker.loadbalancer.server.port=7860 - - tests: - extends: - file: docker-compose.yml - service: backend - env_file: - - .env - build: - context: ../ - dockerfile: base.Dockerfile - command: pytest -vv - healthcheck: - test: "exit 0" - # override deploy labels to avoid conflicts with the backend service - labels: - - traefik.enable=true - - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} - - traefik.http.routers.${STACK_NAME?Variable not set}-tests-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`) - - traefik.http.services.${STACK_NAME?Variable not set}-tests.loadbalancer.server.port=7861 - -networks: - traefik-public: - # For local dev, don't expect an external Traefik network - external: false diff --git a/deploy/docker-compose.with_tests.yml b/deploy/docker-compose.with_tests.yml new file mode 100644 index 000000000..c16c14197 --- /dev/null +++ b/deploy/docker-compose.with_tests.yml @@ -0,0 +1,277 @@ +version: "3.8" + +services: + proxy: + image: traefik:v3.0 + env_file: + - .env + networks: + - ${TRAEFIK_PUBLIC_NETWORK?Variable not set} + - default + volumes: + - /var/run/docker.sock:/var/run/docker.sock + command: + # Enable Docker in Traefik, so that it reads labels from Docker services + - --providers.docker + # Add a constraint to only use services with the label for this stack + # from the env var TRAEFIK_TAG + - --providers.docker.constraints=Label(`traefik.constraint-label-stack`, `${TRAEFIK_TAG?Variable not set}`) + # Do not expose all Docker services, only the ones explicitly exposed + - --providers.docker.exposedbydefault=false + # Enable the access log, with HTTP requests + - --accesslog + # Enable the Traefik log, for configurations and errors + - --log + # Enable the Dashboard and API + - --api + deploy: + placement: + constraints: + - node.role == manager + labels: + # Enable Traefik for this service, to make it available in the public network + - traefik.enable=true + # Use the traefik-public network (declared below) + - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set} + # Use the custom label "traefik.constraint-label=traefik-public" + # This public Traefik will only use services with this label + - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set} + # traefik-http set up only to use the middleware to redirect to https + - traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.scheme=https + - traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.permanent=true + # Handle host with and without "www" to redirect to only one of them + # Uses environment variable DOMAIN + # To disable www redirection remove the Host() you want to discard, here and + # below for HTTPS + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.rule=Host(`${DOMAIN?Variable not set}`) || Host(`www.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.entrypoints=http + # traefik-https the actual router using HTTPS + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.rule=Host(`${DOMAIN?Variable not set}`) || Host(`www.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.entrypoints=https + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls=true + # Use the "le" (Let's Encrypt) resolver created below + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls.certresolver=le + # Define the port inside of the Docker service to use + - traefik.http.services.${STACK_NAME?Variable not set}-proxy.loadbalancer.server.port=80 + # Handle domain with and without "www" to redirect to only one + # To disable www redirection remove the next line + - traefik.http.middlewares.${STACK_NAME?Variable not set}-www-redirect.redirectregex.regex=^https?://(www.)?(${DOMAIN?Variable not set})/(.*) + # Redirect a domain with www to non-www + # To disable it remove the next line + - traefik.http.middlewares.${STACK_NAME?Variable not set}-www-redirect.redirectregex.replacement=https://${DOMAIN?Variable not set}/$${3} + # Redirect a domain without www to www + # To enable it remove the previous line and uncomment the next + # - traefik.http.middlewares.${STACK_NAME}-www-redirect.redirectregex.replacement=https://www.${DOMAIN}/$${3} + # Middleware to redirect www, to disable it remove the next line + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.middlewares=${STACK_NAME?Variable not set}-www-redirect + # Middleware to redirect www, and redirect HTTP to HTTPS + # to disable www redirection remove the section: ${STACK_NAME?Variable not set}-www-redirect, + - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.middlewares=${STACK_NAME?Variable not set}-www-redirect,${STACK_NAME?Variable not set}-https-redirect + + backend: &backend + image: "ogabrielluiz/langflow:latest" + build: + context: ../ + dockerfile: base.Dockerfile + depends_on: + - db + - broker + - result_backend + env_file: + - .env + volumes: + - ../:/app + - ./startup-backend.sh:/startup-backend.sh # Ensure the paths match + command: /startup-backend.sh # Fixed the path + healthcheck: + test: "exit 0" + deploy: + labels: + - traefik.enable=true + - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`) + - traefik.http.services.${STACK_NAME?Variable not set}-backend.loadbalancer.server.port=7860 + + db: + image: postgres:15.4 + volumes: + - app-db-data:/var/lib/postgresql/data/pgdata + environment: + - PGDATA=/var/lib/postgresql/data/pgdata + deploy: + placement: + constraints: + - node.labels.app-db-data == true + healthcheck: + test: "exit 0" + env_file: + - .env + + pgadmin: + image: dpage/pgadmin4 + networks: + - ${TRAEFIK_PUBLIC_NETWORK?Variable not set} + - default + volumes: + - pgadmin-data:/var/lib/pgadmin + env_file: + - .env + deploy: + labels: + - traefik.enable=true + - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set} + - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-http.rule=Host(`pgadmin.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-http.entrypoints=http + - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-http.middlewares=${STACK_NAME?Variable not set}-https-redirect + - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.rule=Host(`pgadmin.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.entrypoints=https + - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.tls=true + - traefik.http.routers.${STACK_NAME?Variable not set}-pgadmin-https.tls.certresolver=le + - traefik.http.services.${STACK_NAME?Variable not set}-pgadmin.loadbalancer.server.port=5050 + + result_backend: + image: redis:6.2.5 + env_file: + - .env + # ports: + # - 6379:6379 + healthcheck: + test: "exit 0" + + celeryworker: + <<: *backend + env_file: + - .env + build: + context: ../ + dockerfile: base.Dockerfile + command: celery -A langflow.worker.celery_app worker --loglevel=INFO --concurrency=1 -n lf-worker@%h + healthcheck: + test: "exit 0" + deploy: + replicas: 1 + + flower: + <<: *backend + env_file: + - .env + networks: + - default + build: + context: ../ + dockerfile: base.Dockerfile + environment: + - FLOWER_PORT=5555 + + command: /bin/sh -c "celery -A langflow.worker.celery_app --broker=${BROKER_URL?Variable not set} flower --port=5555" + deploy: + labels: + - traefik.enable=true + - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set} + - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-flower-http.rule=Host(`flower.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-flower-http.entrypoints=http + - traefik.http.routers.${STACK_NAME?Variable not set}-flower-http.middlewares=${STACK_NAME?Variable not set}-https-redirect + - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.rule=Host(`flower.${DOMAIN?Variable not set}`) + - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.entrypoints=https + - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.tls=true + - traefik.http.routers.${STACK_NAME?Variable not set}-flower-https.tls.certresolver=le + - traefik.http.services.${STACK_NAME?Variable not set}-flower.loadbalancer.server.port=5555 + + frontend: + image: "ogabrielluiz/langflow_frontend:latest" + env_file: + - .env + # user: your-non-root-user + build: + context: ../src/frontend + dockerfile: Dockerfile + args: + - BACKEND_URL=http://backend:7860 + restart: on-failure + deploy: + labels: + - traefik.enable=true + - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`) + - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=80 + + broker: + # RabbitMQ management console + image: rabbitmq:3-management + environment: + - RABBITMQ_DEFAULT_USER=${RABBITMQ_DEFAULT_USER:-admin} + - RABBITMQ_DEFAULT_PASS=${RABBITMQ_DEFAULT_PASS:-admin} + volumes: + - rabbitmq_data:/etc/rabbitmq/ + - rabbitmq_data:/var/lib/rabbitmq/ + - rabbitmq_log:/var/log/rabbitmq/ + ports: + - 5672:5672 + - 15672:15672 + + prometheus: + image: prom/prometheus:v2.37.9 + env_file: + - .env + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + command: + - "--config.file=/etc/prometheus/prometheus.yml" + # ports: + # - 9090:9090 + healthcheck: + test: "exit 0" + deploy: + labels: + - traefik.enable=true + - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-prometheus-http.rule=PathPrefix(`/metrics`) + - traefik.http.services.${STACK_NAME?Variable not set}-prometheus.loadbalancer.server.port=9090 + + grafana: + image: grafana/grafana:8.2.6 + env_file: + - .env + # ports: + # - 3000:3000 + volumes: + - grafana_data:/var/lib/grafana + deploy: + labels: + - traefik.enable=true + - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-grafana-http.rule=PathPrefix(`/grafana`) + - traefik.http.services.${STACK_NAME?Variable not set}-grafana.loadbalancer.server.port=3000 + + tests: + extends: + file: docker-compose.yml + service: backend + env_file: + - .env + build: + context: ../ + dockerfile: base.Dockerfile + command: pytest -vv + healthcheck: + test: "exit 0" + # override deploy labels to avoid conflicts with the backend service + labels: + - traefik.enable=true + - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set} + - traefik.http.routers.${STACK_NAME?Variable not set}-tests-http.rule=PathPrefix(`/api/v1`) || PathPrefix(`/docs`) || PathPrefix(`/health`) + - traefik.http.services.${STACK_NAME?Variable not set}-tests.loadbalancer.server.port=7861 + +volumes: + grafana_data: + app-db-data: + rabbitmq_data: + rabbitmq_log: + pgadmin-data: + +networks: + traefik-public: + # Allow setting it to false for testing + external: false # ${TRAEFIK_PUBLIC_NETWORK_IS_EXTERNAL-true} diff --git a/docs/docs/guides/async-tasks.mdx b/docs/docs/guides/async-tasks.mdx index 5cccc8675..e865fe4b6 100644 --- a/docs/docs/guides/async-tasks.mdx +++ b/docs/docs/guides/async-tasks.mdx @@ -40,5 +40,5 @@ This will set up the following containers: To run the tests for the Async API, you can run the following command: ```bash -docker compose -f docker-compose.test.yml up --exit-code-from tests tests result_backend broker celeryworker db --build +docker compose -f docker-compose.with_tests.yml up --exit-code-from tests tests result_backend broker celeryworker db --build ``` From 5ec118cc6f460a5250a62e725539924c737fc64e Mon Sep 17 00:00:00 2001 From: Gabriel Luiz Freitas Almeida Date: Tue, 26 Sep 2023 20:06:38 -0300 Subject: [PATCH 4/4] =?UTF-8?q?=F0=9F=90=9B=20fix(custom=5Fcomponent.py):?= =?UTF-8?q?=20improve=20error=20message=20formatting=20for=20type=20hint?= =?UTF-8?q?=20error=20in=20build=20method?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The error message for a type hint error in the build method was improved to provide clearer instructions. The traceback message was updated to suggest using PromptTemplate instead of Prompt type. This change improves the readability and usability of the error message. --- src/backend/langflow/interface/custom/custom_component.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/backend/langflow/interface/custom/custom_component.py b/src/backend/langflow/interface/custom/custom_component.py index b0c4f8752..ccc0b08b2 100644 --- a/src/backend/langflow/interface/custom/custom_component.py +++ b/src/backend/langflow/interface/custom/custom_component.py @@ -102,7 +102,10 @@ class CustomComponent(Component, extra=Extra.allow): status_code=400, detail={ "error": "Type hint Error", - "traceback": "Prompt type is not supported in the build method. Try using PromptTemplate instead.", + "traceback": ( + "Prompt type is not supported in the build method." + " Try using PromptTemplate instead." + ), }, ) return args