import os import time from datetime import datetime import psycopg2 from flask import Flask, jsonify, request app = Flask(__name__) DB_CONFIG = { "host": os.getenv("DB_HOST", "db"), "port": int(os.getenv("DB_PORT", "5432")), "dbname": os.getenv("DB_NAME", "guestbook"), "user": os.getenv("DB_USER", "guestbook_user"), "password": os.getenv("DB_PASSWORD", ""), "sslmode": os.getenv("DB_SSLMODE", "prefer"), } APP_PORT = int(os.getenv("APP_PORT", "5000")) def get_connection(): return psycopg2.connect(**DB_CONFIG) def init_db(retries: int = 20, delay: int = 2) -> None: for attempt in range(1, retries + 1): try: with get_connection() as conn: with conn.cursor() as cur: cur.execute( """ CREATE TABLE IF NOT EXISTS messages ( id SERIAL PRIMARY KEY, author VARCHAR(100) NOT NULL, content TEXT NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ) """ ) conn.commit() print("Database initialized.") return except Exception as exc: print(f"Database not ready yet (attempt {attempt}/{retries}): {exc}") time.sleep(delay) raise RuntimeError("Could not initialize the database.") @app.route("/api/health", methods=["GET"]) def health(): try: with get_connection() as conn: with conn.cursor() as cur: cur.execute("SELECT 1") cur.fetchone() return jsonify({"status": "ok", "database": "connected"}), 200 except Exception as exc: return jsonify({"status": "error", "database": str(exc)}), 500 @app.route("/api/messages", methods=["GET"]) def get_messages(): with get_connection() as conn: with conn.cursor() as cur: cur.execute( """ SELECT id, author, content, created_at FROM messages ORDER BY created_at DESC, id DESC """ ) rows = cur.fetchall() data = [ { "id": row[0], "author": row[1], "content": row[2], "created_at": row[3].isoformat(), } for row in rows ] return jsonify(data), 200 @app.route("/api/messages", methods=["POST"]) def add_message(): payload = request.get_json(silent=True) or {} author = (payload.get("author") or "").strip() content = (payload.get("content") or "").strip() if not author or not content: return jsonify({"error": "Fields 'author' and 'content' are required."}), 400 with get_connection() as conn: with conn.cursor() as cur: cur.execute( """ INSERT INTO messages (author, content, created_at) VALUES (%s, %s, %s) RETURNING id, author, content, created_at """, (author, content, datetime.utcnow()), ) row = cur.fetchone() conn.commit() return ( jsonify( { "id": row[0], "author": row[1], "content": row[2], "created_at": row[3].isoformat(), } ), 201, ) if __name__ == "__main__": init_db() app.run(host="0.0.0.0", port=APP_PORT)