Changes to the compse yml and the way and amout of artikeltexte are delivered and taht not duplicates are displayed
This commit is contained in:
@@ -3,6 +3,8 @@ services:
|
||||
build: ./db
|
||||
image: bunker-database:latest
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- backend
|
||||
environment:
|
||||
POSTGRES_USER: ${POSTGRES_USER}
|
||||
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
|
||||
@@ -15,10 +17,32 @@ services:
|
||||
- ./volumes/db-init/data:/docker-entrypoint-initdb.d/data:ro
|
||||
- ./volumes/data:/data
|
||||
|
||||
server-app:
|
||||
server-app-blue:
|
||||
build: ./server-app
|
||||
image: bunker-server-app:latest
|
||||
container_name: server-app-blue
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- proxy
|
||||
- backend
|
||||
environment:
|
||||
APP_PORT: ${APP_PORT}
|
||||
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@database:5432/${POSTGRES_DB}?sslmode=disable
|
||||
expose:
|
||||
- "8080"
|
||||
volumes:
|
||||
- ./volumes/web:/app/web
|
||||
depends_on:
|
||||
- database
|
||||
|
||||
server-app-green:
|
||||
build: ./server-app
|
||||
image: bunker-server-app:latest
|
||||
container_name: server-app-green
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- proxy
|
||||
- backend
|
||||
environment:
|
||||
APP_PORT: ${APP_PORT}
|
||||
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@database:5432/${POSTGRES_DB}?sslmode=disable
|
||||
@@ -33,6 +57,8 @@ services:
|
||||
build: ./ai-worker
|
||||
image: bunker-ai-worker:latest
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- backend
|
||||
environment:
|
||||
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@database:5432/${POSTGRES_DB}?sslmode=disable
|
||||
SD_MODEL_PATH: /app/models/sd15
|
||||
@@ -47,12 +73,16 @@ services:
|
||||
build: ./background-worker
|
||||
image: bunker-background-worker:latest
|
||||
restart: unless-stopped
|
||||
networks:
|
||||
- backend
|
||||
environment:
|
||||
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@database:5432/${POSTGRES_DB}?sslmode=disable
|
||||
RMV_API_KEY: ${RMV_API_KEY}
|
||||
depends_on:
|
||||
- database
|
||||
|
||||
volumes:
|
||||
caddy_data:
|
||||
caddy_config:
|
||||
networks:
|
||||
proxy:
|
||||
external: true
|
||||
backend:
|
||||
driver: bridge
|
||||
@@ -206,7 +206,7 @@ func main() {
|
||||
if err := withConn(r, func(conn *pgx.Conn) error {
|
||||
|
||||
rows, err := conn.Query(r.Context(), `
|
||||
SELECT title, link, summary, image, published_at
|
||||
SELECT article_id, title, link, summary, image, published_at
|
||||
FROM articles
|
||||
WHERE image IS NOT NULL
|
||||
ORDER BY COALESCE(published_at, created_at) DESC
|
||||
@@ -238,16 +238,40 @@ func main() {
|
||||
w.Write([]byte("\n"))
|
||||
flusher.Flush()
|
||||
|
||||
seen := make(map[string]struct{})
|
||||
rowCount := 0
|
||||
|
||||
for rows.Next() {
|
||||
rowCount++
|
||||
var articleID *string
|
||||
var title, link, summary string
|
||||
var image *string
|
||||
var published *time.Time
|
||||
|
||||
if err := rows.Scan(&title, &link, &summary, &image, &published); err != nil {
|
||||
if err := rows.Scan(&articleID, &title, &link, &summary, &image, &published); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
id := ""
|
||||
if articleID != nil {
|
||||
id = strings.TrimSpace(*articleID)
|
||||
}
|
||||
if id == "" {
|
||||
if link != "" {
|
||||
id = link
|
||||
} else if title != "" {
|
||||
id = title
|
||||
} else {
|
||||
id = fmt.Sprintf("row:%d", rowCount)
|
||||
}
|
||||
}
|
||||
if _, exists := seen[id]; exists {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
|
||||
item := map[string]interface{}{
|
||||
"id": id,
|
||||
"title": title,
|
||||
"link": link,
|
||||
"text": summary,
|
||||
|
||||
@@ -38,10 +38,16 @@ async function loadNews() {
|
||||
const lines = text.split("\n").map((line) => line.trim()).filter(Boolean);
|
||||
|
||||
const items = [];
|
||||
const seen = new Set();
|
||||
for (const line of lines) {
|
||||
try {
|
||||
const parsed = JSON.parse(line);
|
||||
const fallbackTitle = stripTags(parsed.title);
|
||||
const id = parsed.id || parsed.link || fallbackTitle || `idx:${items.length}`;
|
||||
if (seen.has(id)) continue;
|
||||
seen.add(id);
|
||||
items.push({
|
||||
id,
|
||||
title: stripTags(parsed.title),
|
||||
text: stripTags(parsed.text),
|
||||
link: parsed.link,
|
||||
@@ -49,7 +55,7 @@ async function loadNews() {
|
||||
} catch (err) {
|
||||
console.warn("NDJSON parse error", err);
|
||||
}
|
||||
if (items.length >= 60) break;
|
||||
if (items.length >= 20) break;
|
||||
}
|
||||
|
||||
newsContainer.innerHTML = "";
|
||||
|
||||
@@ -32,9 +32,14 @@ async function ladeNews() {
|
||||
|
||||
const loadingEl = null;
|
||||
|
||||
container.innerHTML = "";
|
||||
|
||||
const newsIndex = new Map();
|
||||
const maxItems = 20;
|
||||
let renderedCount = 0;
|
||||
|
||||
const getKey = (nachricht) => {
|
||||
if (nachricht?.id) return `id:${nachricht.id}`;
|
||||
if (nachricht?.link) return `link:${nachricht.link}`;
|
||||
if (nachricht?.title) return `title:${stripTags(nachricht.title)}`;
|
||||
if (nachricht?.publishedAt) return `ts:${nachricht.publishedAt}`;
|
||||
@@ -109,13 +114,15 @@ async function ladeNews() {
|
||||
const existing = newsIndex.get(key);
|
||||
if (existing) {
|
||||
updateFields(existing, nachricht);
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
const state = buildItem(nachricht);
|
||||
updateFields(state, nachricht);
|
||||
newsIndex.set(key, state);
|
||||
container.appendChild(state.item);
|
||||
renderedCount += 1;
|
||||
return true;
|
||||
};
|
||||
|
||||
try {
|
||||
@@ -136,6 +143,7 @@ async function ladeNews() {
|
||||
const decoder = new TextDecoder("utf-8");
|
||||
let buffer = "";
|
||||
|
||||
let stop = false;
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
@@ -148,19 +156,27 @@ async function ladeNews() {
|
||||
const s = line.trim();
|
||||
if (!s) continue;
|
||||
try {
|
||||
renderItem(JSON.parse(s));
|
||||
foundAny = true;
|
||||
const added = renderItem(JSON.parse(s));
|
||||
if (added) foundAny = true;
|
||||
if (renderedCount >= maxItems) {
|
||||
stop = true;
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn("NDJSON parse error:", s.slice(0, 200));
|
||||
}
|
||||
}
|
||||
if (stop) break;
|
||||
}
|
||||
if (stop) {
|
||||
await reader.cancel();
|
||||
}
|
||||
|
||||
const last = buffer.trim();
|
||||
if (last) {
|
||||
if (last && renderedCount < maxItems) {
|
||||
try {
|
||||
renderItem(JSON.parse(last));
|
||||
foundAny = true;
|
||||
const added = renderItem(JSON.parse(last));
|
||||
if (added) foundAny = true;
|
||||
} catch {}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user