From 06afbbf87b0ba27b8985a1fabae5df993b1be5a3 Mon Sep 17 00:00:00 2001 From: rootflo-hardik Date: Mon, 15 Jun 2026 17:33:47 +0530 Subject: [PATCH 1/4] floware init script - for creating db on startup --- wavefront/server/docker/floware.Dockerfile | 7 +++-- wavefront/server/scripts/floware-init.sh | 33 ++++++++++++++++++++++ 2 files changed, 37 insertions(+), 3 deletions(-) create mode 100644 wavefront/server/scripts/floware-init.sh diff --git a/wavefront/server/docker/floware.Dockerfile b/wavefront/server/docker/floware.Dockerfile index 15d1fe1c..92f2790f 100644 --- a/wavefront/server/docker/floware.Dockerfile +++ b/wavefront/server/docker/floware.Dockerfile @@ -36,6 +36,9 @@ COPY wavefront/server/plugins/authenticator /app/plugins/authenticator COPY wavefront/server/apps/floware /app/apps/floware +COPY wavefront/server/scripts/floware-init.sh /app/scripts/floware-init.sh +RUN chmod +x /app/scripts/floware-init.sh + RUN uv sync --package floware --frozen --no-dev # Create a non-root user and change ownership of the /app directory @@ -44,6 +47,4 @@ RUN useradd -m -u 1000 floware && \ USER floware -WORKDIR /app/apps/floware/floware - -CMD ["uv", "run", "server.py"] +ENTRYPOINT ["/app/scripts/floware-init.sh"] diff --git a/wavefront/server/scripts/floware-init.sh b/wavefront/server/scripts/floware-init.sh new file mode 100644 index 00000000..cf60d191 --- /dev/null +++ b/wavefront/server/scripts/floware-init.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -e + +export PATH="/app/.venv/bin:$PATH" + +if [ "${FLOWARE_DB_CREATE}" = "true" ]; then + echo "Creating Floware database if not exists..." + python3 -c " +import psycopg2, os + +host = os.environ['DB_HOST'] +user = os.environ['DB_USERNAME'] +password = os.environ['DB_PASSWORD'] +dbname = os.environ['DB_NAME'] + +conn = psycopg2.connect(host=host, user=user, password=password, dbname='postgres') +conn.autocommit = True +cur = conn.cursor() +cur.execute(\"SELECT 1 FROM pg_database WHERE datname = %s\", (dbname,)) + +if not cur.fetchone(): + cur.execute('CREATE DATABASE \"' + dbname.replace('\"', '\"\"') + '\"') + print('Database created') +else: + print('Database already exists, skipping') +conn.close() +" +else + echo "FLOWARE_DB_CREATE is not true, skipping database creation" +fi + +cd /app/apps/floware/floware +exec uv run server.py From 3ba9e432f494ab153c30c791d22a299483e19227 Mon Sep 17 00:00:00 2001 From: rootflo-hardik Date: Tue, 16 Jun 2026 10:46:26 +0530 Subject: [PATCH 2/4] create pg vector extension as well if not exists --- wavefront/server/scripts/floware-init.sh | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/wavefront/server/scripts/floware-init.sh b/wavefront/server/scripts/floware-init.sh index cf60d191..01a44f62 100644 --- a/wavefront/server/scripts/floware-init.sh +++ b/wavefront/server/scripts/floware-init.sh @@ -24,6 +24,13 @@ if not cur.fetchone(): else: print('Database already exists, skipping') conn.close() + +conn = psycopg2.connect(host=host, user=user, password=password, dbname=dbname) +conn.autocommit = True +cur = conn.cursor() +cur.execute('CREATE EXTENSION IF NOT EXISTS vector') +print('Ensured vector extension exists') +conn.close() " else echo "FLOWARE_DB_CREATE is not true, skipping database creation" From b36c054b19e1549f33509e452559cc280b82a499 Mon Sep 17 00:00:00 2001 From: rootflo-hardik Date: Tue, 16 Jun 2026 15:06:01 +0530 Subject: [PATCH 3/4] modified hnsw index on embedding to non conc index --- ...f2a1c3b5d9_add_hnsw_index_on_embeddings.py | 83 +++++++------------ 1 file changed, 32 insertions(+), 51 deletions(-) diff --git a/wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_04_10_1000-e8f2a1c3b5d9_add_hnsw_index_on_embeddings.py b/wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_04_10_1000-e8f2a1c3b5d9_add_hnsw_index_on_embeddings.py index 6c00f325..49e3bcc8 100644 --- a/wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_04_10_1000-e8f2a1c3b5d9_add_hnsw_index_on_embeddings.py +++ b/wavefront/server/modules/db_repo_module/db_repo_module/alembic/versions/2026_04_10_1000-e8f2a1c3b5d9_add_hnsw_index_on_embeddings.py @@ -24,61 +24,42 @@ def upgrade() -> None: # dimensions so we cast inline. # embedding_vector → 512 dims (CLIP image / text embeddings) # embedding_vector_1 → 1024 dims (DINO image embeddings) - # - # CREATE INDEX CONCURRENTLY cannot run inside a transaction block. - # SQLAlchemy 2.x autobegins a transaction on op.get_bind(), and - # execution_options(isolation_level=AUTOCOMMIT) is rejected while a - # Transaction object is active. We get a fresh AUTOCOMMIT connection - # directly from the underlying sync engine instead. - bind = op.get_bind() - sync_engine = getattr(bind.engine, 'sync_engine', bind.engine) + conn = op.get_bind() - with sync_engine.execution_options(isolation_level='AUTOCOMMIT').connect() as conn: - conn.execute(text("SET maintenance_work_mem = '2GB'")) + conn.execute(text("SET LOCAL maintenance_work_mem = '2GB'")) - conn.execute( - text(""" - CREATE INDEX CONCURRENTLY IF NOT EXISTS - ix_kbe_embedding_vector_hnsw_cosine - ON knowledge_base_embeddings - USING hnsw ((embedding_vector::vector(512)) vector_cosine_ops) - WITH (m = 16, ef_construction = 64) - """) - ) + conn.execute( + text(""" + CREATE INDEX IF NOT EXISTS + ix_kbe_embedding_vector_hnsw_cosine + ON knowledge_base_embeddings + USING hnsw ((embedding_vector::vector(512)) vector_cosine_ops) + WITH (m = 16, ef_construction = 64) + """) + ) - conn.execute( - text(""" - CREATE INDEX CONCURRENTLY IF NOT EXISTS - ix_kbe_embedding_vector_1_hnsw_cosine - ON knowledge_base_embeddings - USING hnsw ((embedding_vector_1::vector(1024)) vector_cosine_ops) - WITH (m = 16, ef_construction = 64) - """) - ) + conn.execute( + text(""" + CREATE INDEX IF NOT EXISTS + ix_kbe_embedding_vector_1_hnsw_cosine + ON knowledge_base_embeddings + USING hnsw ((embedding_vector_1::vector(1024)) vector_cosine_ops) + WITH (m = 16, ef_construction = 64) + """) + ) - conn.execute( - text(""" - CREATE INDEX CONCURRENTLY IF NOT EXISTS - ix_kbe_token_gin - ON knowledge_base_embeddings - USING gin (token) - """) - ) + conn.execute( + text(""" + CREATE INDEX IF NOT EXISTS + ix_kbe_token_gin + ON knowledge_base_embeddings + USING gin (token) + """) + ) def downgrade() -> None: - bind = op.get_bind() - sync_engine = getattr(bind.engine, 'sync_engine', bind.engine) - - with sync_engine.execution_options(isolation_level='AUTOCOMMIT').connect() as conn: - conn.execute( - text( - 'DROP INDEX CONCURRENTLY IF EXISTS ix_kbe_embedding_vector_hnsw_cosine' - ) - ) - conn.execute( - text( - 'DROP INDEX CONCURRENTLY IF EXISTS ix_kbe_embedding_vector_1_hnsw_cosine' - ) - ) - conn.execute(text('DROP INDEX CONCURRENTLY IF EXISTS ix_kbe_token_gin')) + conn = op.get_bind() + conn.execute(text('DROP INDEX IF EXISTS ix_kbe_embedding_vector_hnsw_cosine')) + conn.execute(text('DROP INDEX IF EXISTS ix_kbe_embedding_vector_1_hnsw_cosine')) + conn.execute(text('DROP INDEX IF EXISTS ix_kbe_token_gin')) From f183f641e7d90a18c51ecdc6ebc06376c4601b00 Mon Sep 17 00:00:00 2001 From: rootflo-hardik Date: Tue, 16 Jun 2026 16:45:47 +0530 Subject: [PATCH 4/4] no need for public/private keys when kms enabled --- .../auth_module/auth_module/services/token_service.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/wavefront/server/modules/auth_module/auth_module/services/token_service.py b/wavefront/server/modules/auth_module/auth_module/services/token_service.py index 33e94f9d..3aec7f8c 100644 --- a/wavefront/server/modules/auth_module/auth_module/services/token_service.py +++ b/wavefront/server/modules/auth_module/auth_module/services/token_service.py @@ -36,8 +36,8 @@ def __init__( audience: str = 'https://floware.rootflo.ai', ): self.is_dev = app_env == 'dev' or (kms_service is None) - self.private_key = self._load_key(private_key) - self.public_key = self._load_key(public_key) + self.private_key = self._load_key(private_key) if self.is_dev else None + self.public_key = self._load_key(public_key) if self.is_dev else None self.algorithm = TokenAlgorithms.RS256.value if self.is_dev else algorithm.value self.token_expiry = int(token_expiry) self.temporary_token_expiry = int(temporary_token_expiry) @@ -46,8 +46,9 @@ def __init__( self.audience = audience def _load_key(self, key: str): - key = base64.b64decode(key).decode('ascii') - return key + if not key: + return None + return base64.b64decode(key).decode('ascii') def create_token( self,