anky2002 commited on
Commit
58e1df0
·
verified ·
1 Parent(s): 5adcda5

fix(P0): Migration uses vector(768), remove direct port exposure in prod compose, add lockfile note

Browse files
backend/alembic/versions/001_initial.py CHANGED
@@ -1,18 +1,17 @@
1
- """Initial schema - metadata driven
2
 
3
  Revision ID: 001_initial
4
  Revises: None
5
  Create Date: 2026-05-12
6
 
7
- This migration intentionally creates tables from SQLAlchemy metadata so local
8
- setup stays aligned with the rapidly evolving app models.
9
  """
10
  from typing import Sequence, Union
11
 
12
  from alembic import op
13
  import sqlalchemy as sa
14
 
15
- # revision identifiers, used by Alembic.
16
  revision: str = "001_initial"
17
  down_revision: Union[str, None] = None
18
  branch_labels: Union[str, Sequence[str], None] = None
@@ -21,65 +20,51 @@ depends_on: Union[str, Sequence[str], None] = None
21
 
22
  def _import_all_models() -> None:
23
  """Import every module that declares SQLAlchemy models."""
24
- # Core model modules
25
- import app.models.user # noqa: F401
26
- import app.models.job # noqa: F401
27
- import app.models.application # noqa: F401
28
- import app.models.resume # noqa: F401
29
- import app.models.scraper # noqa: F401
30
- import app.models.llm # noqa: F401
31
- import app.models.alerts # noqa: F401
32
-
33
- # A few later-stage models currently live in route/service modules.
34
- # Importing them registers their tables on Base.metadata.
35
- import app.api.routes.bookmarks # noqa: F401
36
- import app.api.routes.webhooks # noqa: F401
37
- import app.api.routes.reminders # noqa: F401
38
- import app.api.routes.cover_letters # noqa: F401
39
- import app.api.routes.qa_bank # noqa: F401
40
- import app.services.analytics # noqa: F401
41
 
42
 
43
  def upgrade() -> None:
44
  conn = op.get_bind()
45
 
46
- # Required extensions. pgvector requires the Docker image pgvector/pgvector:pg17.
47
  op.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"')
48
  op.execute('CREATE EXTENSION IF NOT EXISTS "pg_trgm"')
49
  op.execute('CREATE EXTENSION IF NOT EXISTS "vector"')
50
 
51
  _import_all_models()
52
  from app.core.database import Base
53
-
54
- # Create all ORM-backed tables.
55
  Base.metadata.create_all(bind=conn)
56
 
57
- # Create semantic search table manually because SQLAlchemy does not ship a
58
- # native pgvector type. The semantic search service writes to this table.
59
- op.execute(
60
- """
61
  CREATE TABLE IF NOT EXISTS job_embeddings (
62
  job_id UUID PRIMARY KEY REFERENCES jobs(id) ON DELETE CASCADE,
63
  text_hash VARCHAR(32) NOT NULL,
64
  updated_at TIMESTAMPTZ DEFAULT now(),
65
- embedding vector(1536)
66
  )
67
- """
68
- )
69
- op.execute(
70
- """
71
  CREATE INDEX IF NOT EXISTS idx_job_embeddings_vector
72
  ON job_embeddings USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100)
73
- """
74
- )
75
 
76
- # Useful search indexes. Ignore failures on repeated local runs.
77
- op.execute(
78
- """
79
  CREATE INDEX IF NOT EXISTS idx_jobs_fts ON jobs
80
  USING gin(to_tsvector('english', coalesce(title, '') || ' ' || coalesce(company_name, '') || ' ' || coalesce(description_text, '')))
81
- """
82
- )
83
  op.execute("CREATE INDEX IF NOT EXISTS idx_jobs_title_trgm ON jobs USING gin(title gin_trgm_ops)")
84
 
85
 
@@ -88,8 +73,6 @@ def downgrade() -> None:
88
  op.execute("DROP TABLE IF EXISTS job_embeddings")
89
  _import_all_models()
90
  from app.core.database import Base
91
-
92
- # Drop in dependency order.
93
  Base.metadata.drop_all(bind=conn)
94
  op.execute('DROP EXTENSION IF EXISTS "vector"')
95
  op.execute('DROP EXTENSION IF EXISTS "pg_trgm"')
 
1
+ """Initial schema - creates all tables from ORM models.
2
 
3
  Revision ID: 001_initial
4
  Revises: None
5
  Create Date: 2026-05-12
6
 
7
+ NOTE: This migration uses Base.metadata.create_all() for rapid iteration.
8
+ For production, replace with explicit op.create_table() calls.
9
  """
10
  from typing import Sequence, Union
11
 
12
  from alembic import op
13
  import sqlalchemy as sa
14
 
 
15
  revision: str = "001_initial"
16
  down_revision: Union[str, None] = None
17
  branch_labels: Union[str, Sequence[str], None] = None
 
20
 
21
  def _import_all_models() -> None:
22
  """Import every module that declares SQLAlchemy models."""
23
+ import app.models.user # noqa
24
+ import app.models.job # noqa
25
+ import app.models.application # noqa
26
+ import app.models.resume # noqa
27
+ import app.models.scraper # noqa
28
+ import app.models.llm # noqa
29
+ import app.models.alerts # noqa
30
+ import app.api.routes.bookmarks # noqa
31
+ import app.api.routes.webhooks # noqa
32
+ import app.api.routes.reminders # noqa
33
+ import app.api.routes.cover_letters # noqa
34
+ import app.api.routes.qa_bank # noqa
35
+ import app.services.analytics # noqa
 
 
 
 
36
 
37
 
38
  def upgrade() -> None:
39
  conn = op.get_bind()
40
 
 
41
  op.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp"')
42
  op.execute('CREATE EXTENSION IF NOT EXISTS "pg_trgm"')
43
  op.execute('CREATE EXTENSION IF NOT EXISTS "vector"')
44
 
45
  _import_all_models()
46
  from app.core.database import Base
 
 
47
  Base.metadata.create_all(bind=conn)
48
 
49
+ # Semantic search table — uses 768 dims (nomic-embed-text via Ollama)
50
+ op.execute("""
 
 
51
  CREATE TABLE IF NOT EXISTS job_embeddings (
52
  job_id UUID PRIMARY KEY REFERENCES jobs(id) ON DELETE CASCADE,
53
  text_hash VARCHAR(32) NOT NULL,
54
  updated_at TIMESTAMPTZ DEFAULT now(),
55
+ embedding vector(768)
56
  )
57
+ """)
58
+ op.execute("""
 
 
59
  CREATE INDEX IF NOT EXISTS idx_job_embeddings_vector
60
  ON job_embeddings USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100)
61
+ """)
 
62
 
63
+ # Full-text search indexes
64
+ op.execute("""
 
65
  CREATE INDEX IF NOT EXISTS idx_jobs_fts ON jobs
66
  USING gin(to_tsvector('english', coalesce(title, '') || ' ' || coalesce(company_name, '') || ' ' || coalesce(description_text, '')))
67
+ """)
 
68
  op.execute("CREATE INDEX IF NOT EXISTS idx_jobs_title_trgm ON jobs USING gin(title gin_trgm_ops)")
69
 
70
 
 
73
  op.execute("DROP TABLE IF EXISTS job_embeddings")
74
  _import_all_models()
75
  from app.core.database import Base
 
 
76
  Base.metadata.drop_all(bind=conn)
77
  op.execute('DROP EXTENSION IF EXISTS "vector"')
78
  op.execute('DROP EXTENSION IF EXISTS "pg_trgm"')