diff --git a/backend/Dockerfile b/backend/Dockerfile index d87325f7dbfa..ece2915082c7 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,7 +1,8 @@ FROM python:3.11-slim-bullseye RUN apt-get update \ - && apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential \ + && apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler \ + libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential curl \ && rm -rf /var/lib/apt/lists/* COPY ./requirements/default.txt /tmp/requirements.txt diff --git a/backend/Dockerfile.background b/backend/Dockerfile.background index 4b54c8827926..ebd28293aae4 100644 --- a/backend/Dockerfile.background +++ b/backend/Dockerfile.background @@ -1,7 +1,8 @@ FROM python:3.11-slim-bullseye RUN apt-get update \ - && apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential cron \ + && apt-get install -y git cmake pkg-config libprotobuf-c-dev protobuf-compiler \ + libprotobuf-dev libgoogle-perftools-dev libpq-dev build-essential cron curl \ && rm -rf /var/lib/apt/lists/* COPY ./requirements/default.txt /tmp/requirements.txt diff --git a/backend/danswer/main.py b/backend/danswer/main.py index 3d4694327060..b361b155f69c 100644 --- a/backend/danswer/main.py +++ b/backend/danswer/main.py @@ -13,6 +13,7 @@ from danswer.configs.app_configs import WEB_DOMAIN from danswer.datastores.qdrant.indexing import list_collections from danswer.server.admin import router as admin_router from danswer.server.event_loading import router as event_processing_router +from danswer.server.health import router as health_router from danswer.server.search_backend import router as backend_router from danswer.utils.logging import setup_logger from fastapi import FastAPI @@ -39,6 +40,7 @@ def get_application() -> FastAPI: application.include_router(backend_router) application.include_router(event_processing_router) application.include_router(admin_router) + application.include_router(health_router) application.include_router( fastapi_users.get_auth_router(auth_backend), diff --git a/backend/danswer/server/admin.py b/backend/danswer/server/admin.py index 4248ed40274d..ebb5c2bae621 100644 --- a/backend/danswer/server/admin.py +++ b/backend/danswer/server/admin.py @@ -21,7 +21,9 @@ from danswer.dynamic_configs.interface import ConfigNotFoundError from danswer.server.models import AuthStatus from danswer.server.models import AuthUrl from danswer.server.models import GDriveCallback +from danswer.server.models import IndexAttemptRequest from danswer.server.models import IndexAttemptSnapshot +from danswer.server.models import ListIndexAttemptsResponse from danswer.utils.logging import setup_logger from fastapi import APIRouter from fastapi import Depends @@ -69,11 +71,6 @@ def modify_slack_config( update_slack_config(slack_config) -class IndexAttemptRequest(BaseModel): - input_type: InputType = InputType.PULL - connector_specific_config: dict[str, Any] - - @router.post("/connectors/{source}/index-attempt", status_code=201) def index( source: DocumentSource, @@ -100,10 +97,6 @@ def index( ) -class ListIndexAttemptsResponse(BaseModel): - index_attempts: list[IndexAttemptSnapshot] - - @router.get("/connectors/{source}/index-attempt") def list_index_attempts( source: DocumentSource, diff --git a/backend/danswer/server/health.py b/backend/danswer/server/health.py new file mode 100644 index 000000000000..a9a652783ffc --- /dev/null +++ b/backend/danswer/server/health.py @@ -0,0 +1,10 @@ +from danswer.server.models import HealthCheckResponse +from fastapi import APIRouter + + +router = APIRouter() + + +@router.get("/health") +def healthcheck() -> HealthCheckResponse: + return {"status": "ok"} diff --git a/backend/danswer/server/models.py b/backend/danswer/server/models.py index 3df71b42b7a6..05724bb7309e 100644 --- a/backend/danswer/server/models.py +++ b/backend/danswer/server/models.py @@ -1,12 +1,18 @@ from datetime import datetime from typing import Any +from typing import Literal from danswer.configs.constants import DocumentSource +from danswer.connectors.models import InputType from danswer.datastores.interfaces import DatastoreFilter from danswer.db.models import IndexingStatus from pydantic import BaseModel +class HealthCheckResponse(BaseModel): + status: Literal["ok"] + + class AuthStatus(BaseModel): authenticated: bool @@ -51,6 +57,11 @@ class UserByEmail(BaseModel): user_email: str +class IndexAttemptRequest(BaseModel): + input_type: InputType = InputType.PULL + connector_specific_config: dict[str, Any] + + class IndexAttemptSnapshot(BaseModel): connector_specific_config: dict[str, Any] status: IndexingStatus @@ -60,5 +71,5 @@ class IndexAttemptSnapshot(BaseModel): docs_indexed: int -class ListWebsiteIndexAttemptsResponse(BaseModel): +class ListIndexAttemptsResponse(BaseModel): index_attempts: list[IndexAttemptSnapshot] diff --git a/deployment/docker-compose.dev.yml b/deployment/docker-compose.dev.yml index 472817a5c4d1..01192fbcb11c 100644 --- a/deployment/docker-compose.dev.yml +++ b/deployment/docker-compose.dev.yml @@ -35,7 +35,7 @@ services: web_server: build: context: ../web - dockerfile: Dockerfile + dockerfile: Dockerfile.dev depends_on: - api_server restart: always @@ -43,7 +43,6 @@ services: - .env environment: - INTERNAL_URL=http://api_server:8080 - - NODE_ENV=development ports: - "3000:3000" relational_db: @@ -59,6 +58,8 @@ services: vector_db: image: qdrant/qdrant:v1.1.3 restart: always + ports: + - "6333:6333" volumes: - qdrant_volume:/qdrant/storage volumes: diff --git a/deployment/docker-compose.prod.yml b/deployment/docker-compose.prod.yml index 45c1978cc423..28561f3fcbb2 100644 --- a/deployment/docker-compose.prod.yml +++ b/deployment/docker-compose.prod.yml @@ -33,7 +33,7 @@ services: web_server: build: context: ../web - dockerfile: Dockerfile + dockerfile: Dockerfile.prod depends_on: - api_server restart: always @@ -41,7 +41,6 @@ services: - .env environment: - INTERNAL_URL=http://api_server:8080 - - NODE_ENV=production relational_db: image: postgres:15.2-alpine restart: always diff --git a/web/Dockerfile.dev b/web/Dockerfile.dev new file mode 100644 index 000000000000..0bcabc117e42 --- /dev/null +++ b/web/Dockerfile.dev @@ -0,0 +1,32 @@ +FROM node:18-alpine + +WORKDIR /app + +# Install dependencies based on the preferred package manager +COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ +RUN \ + if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ + elif [ -f package-lock.json ]; then npm ci; \ + elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \ + # Allow install without lockfile, so example works even without Node.js installed locally + else echo "Warning: Lockfile not found. It is recommended to commit lockfiles to version control." && yarn install; \ + fi + +COPY src ./src +COPY public ./public +COPY next.config.js . +COPY tsconfig.json . + +# Next.js collects completely anonymous telemetry data about general usage. Learn more here: https://nextjs.org/telemetry +# Uncomment the following line to disable telemetry at run time +ENV NEXT_TELEMETRY_DISABLED 1 + +# Note: Don't expose ports here, Compose will handle that for us + +# Start Next.js in development mode based on the preferred package manager +CMD \ + if [ -f yarn.lock ]; then yarn dev; \ + elif [ -f package-lock.json ]; then npm run dev; \ + elif [ -f pnpm-lock.yaml ]; then pnpm dev; \ + else yarn dev; \ + fi \ No newline at end of file diff --git a/web/Dockerfile b/web/Dockerfile.prod similarity index 100% rename from web/Dockerfile rename to web/Dockerfile.prod diff --git a/web/src/app/admin/connectors/github/page.tsx b/web/src/app/admin/connectors/github/page.tsx index 8ea2586303ec..9212405eeb9d 100644 --- a/web/src/app/admin/connectors/github/page.tsx +++ b/web/src/app/admin/connectors/github/page.tsx @@ -4,10 +4,14 @@ import * as Yup from "yup"; import { IndexForm } from "@/components/admin/connectors/Form"; import { GithubIcon } from "@/components/icons/icons"; import { TextFormField } from "@/components/admin/connectors/Field"; +import { HealthCheckBanner } from "@/components/health/healthcheck"; export default function Page() { return (
The backend is currently unavailable.
+ ++ If this is your initial setup or you just updated your Danswer + deployment, this is likely because the backend is still starting up. + Give it a minute or two, and then refresh the page. If that does not + work, make sure the backend is setup and/or contact an administrator. +
+