Skip to content
This repository was archived by the owner on Feb 9, 2026. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
357 changes: 357 additions & 0 deletions .github/workflows/ephemeral.yml

Large diffs are not rendered by default.

446 changes: 223 additions & 223 deletions .github/workflows/pipeline.yml

Large diffs are not rendered by default.

27 changes: 27 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,33 @@ This project demonstrates a modern microservices architecture that processes mes
The system consists of multiple microservices communicating via message queues:

![Arch](demo-apps.svg)

### Complete Message Flow

1. **User Request**: User accesses `ascii-frontend` and submits a query (e.g., "kubernetes")
2. **Enqueuer Processing**:
- Receives the query via REST API (`POST /add`)
- Searches Google Images using Chromium headless browser
- Picks the first suitable image URL
- Publishes message with image URL to NATS queue (`{ENV}.queue-{QUEUE_NAME}`)
- Subscribes to result queue (`{ENV}.result-queue`) to wait for ASCII art response
3. **Memorizer Processing**:
- Listens to NATS queue for new messages
- Downloads the image from the URL
- Generates ASCII art (terminal, file, and HTML formats)
- Stores the ASCII art output in Redis (with environment prefix: `{ENV}:{MESSAGE_ID}:ascii_*`)
- Publishes the result back to NATS result queue
4. **Enqueuer Response**:
- Receives ASCII art result from NATS result queue
- Returns complete response to the user (including image URL and ASCII art)
5. **Writer Storage**:
- Monitors Redis for new entries
- Retrieves processed messages with ASCII art
- Stores everything in PostgreSQL (environment-specific tables)
- Provides query endpoints for historical data

### Technology Stack

- **Communication**: NATS for message queuing
- **Storage**: Redis for temporary storage, PostgreSQL for persistent storage
- **Deployment**: Kubernetes with Kustomize configurations
Expand Down
39 changes: 39 additions & 0 deletions apps/ascii-frontend/kustomize/ephemeral-base/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: ascii-frontend
spec:
replicas: 1
selector:
matchLabels:
app: ascii-frontend
template:
metadata:
labels:
app: ascii-frontend
spec:
containers:
- name: ascii-frontend
image: registry.fullstack.pw/library/ascii-frontend:latest
imagePullPolicy: Always
ports:
- containerPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 15
periodSeconds: 20
25 changes: 25 additions & 0 deletions apps/ascii-frontend/kustomize/ephemeral-base/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: ascii-frontend
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
external-dns.alpha.kubernetes.io/hostname: "endpoint"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: "traefik"
tls:
- hosts:
- "endpoint"
secretName: ascii-frontend-tls-ephemeral
rules:
- host: "endpoint"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: ascii-frontend
port:
number: 80
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- service.yaml
- deployment.yaml
- ingress.yaml

namespace: default
13 changes: 13 additions & 0 deletions apps/ascii-frontend/kustomize/ephemeral-base/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: ascii-frontend
spec:
selector:
app: ascii-frontend
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
type: ClusterIP
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: default

resources:
- ../../ephemeral-base

images:
- name: registry.fullstack.pw/library/ascii-frontend
newTag: pr-will-be-replaced

patches:
- patch: |-
- op: replace
path: /metadata/annotations/external-dns.alpha.kubernetes.io~1hostname
value: "dev.ascii-frontend.fullstack.pw"
- op: replace
path: /spec/tls/0/hosts/0
value: "dev.ascii-frontend.fullstack.pw"
- op: replace
path: /spec/rules/0/host
value: "dev.ascii-frontend.fullstack.pw"
target:
kind: Ingress
name: ascii-frontend
39 changes: 39 additions & 0 deletions apps/enqueuer/kustomize/ephemeral-base/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: enqueuer
spec:
replicas: 1
selector:
matchLabels:
app: enqueuer
template:
metadata:
labels:
app: enqueuer
spec:
containers:
- name: enqueuer
image: registry.fullstack.pw/library/enqueuer:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: ENV
value: "ephemeral"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: opentelemetry-collector.observability.svc.cluster.local:4317
- name: NATS_URL
value: nats.fullstack.pw:4222
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
25 changes: 25 additions & 0 deletions apps/enqueuer/kustomize/ephemeral-base/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: enqueuer
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
external-dns.alpha.kubernetes.io/hostname: "endpoint"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: "traefik"
tls:
- hosts:
- "endpoint"
secretName: enqueuer-tls-ephemeral
rules:
- host: "endpoint"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: enqueuer
port:
number: 8080
9 changes: 9 additions & 0 deletions apps/enqueuer/kustomize/ephemeral-base/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- service.yaml
- deployment.yaml
- ingress.yaml

namespace: default
13 changes: 13 additions & 0 deletions apps/enqueuer/kustomize/ephemeral-base/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: enqueuer
spec:
selector:
app: enqueuer
ports:
- port: 8080
targetPort: 8080
protocol: TCP
name: http
type: ClusterIP
26 changes: 26 additions & 0 deletions apps/enqueuer/kustomize/overlays/ephemeral/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: default

resources:
- ../../ephemeral-base

images:
- name: registry.fullstack.pw/library/enqueuer
newTag: pr-will-be-replaced

patches:
- patch: |-
- op: replace
path: /metadata/annotations/external-dns.alpha.kubernetes.io~1hostname
value: "dev.enqueuer.fullstack.pw"
- op: replace
path: /spec/tls/0/hosts/0
value: "dev.enqueuer.fullstack.pw"
- op: replace
path: /spec/rules/0/host
value: "dev.enqueuer.fullstack.pw"
target:
kind: Ingress
name: enqueuer
51 changes: 51 additions & 0 deletions apps/memorizer/kustomize/ephemeral-base/deployment.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: memorizer
spec:
replicas: 1
selector:
matchLabels:
app: memorizer
template:
metadata:
labels:
app: memorizer
spec:
containers:
- name: memorizer
image: registry.fullstack.pw/library/memorizer:latest
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: ENV
value: "ephemeral"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: opentelemetry-collector.observability.svc.cluster.local:4317
- name: QUEUE_NAMES
value: "queue-ephemeral"
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: cluster-secrets
key: REDIS_PASSWORD
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 200m
memory: 256Mi
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
25 changes: 25 additions & 0 deletions apps/memorizer/kustomize/ephemeral-base/ingress.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: memorizer
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
external-dns.alpha.kubernetes.io/hostname: "endpoint"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: "traefik"
tls:
- hosts:
- "endpoint"
secretName: memorizer-tls-ephemeral
rules:
- host: "endpoint"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: memorizer
port:
number: 8080
9 changes: 9 additions & 0 deletions apps/memorizer/kustomize/ephemeral-base/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- service.yaml
- deployment.yaml
- ingress.yaml

namespace: default
13 changes: 13 additions & 0 deletions apps/memorizer/kustomize/ephemeral-base/service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
apiVersion: v1
kind: Service
metadata:
name: memorizer
spec:
selector:
app: memorizer
ports:
- port: 8080
targetPort: 8080
protocol: TCP
name: http
type: ClusterIP
26 changes: 26 additions & 0 deletions apps/memorizer/kustomize/overlays/ephemeral/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

namespace: default

resources:
- ../../ephemeral-base

images:
- name: registry.fullstack.pw/library/memorizer
newTag: pr-will-be-replaced

patches:
- patch: |-
- op: replace
path: /metadata/annotations/external-dns.alpha.kubernetes.io~1hostname
value: "dev.memorizer.fullstack.pw"
- op: replace
path: /spec/tls/0/hosts/0
value: "dev.memorizer.fullstack.pw"
- op: replace
path: /spec/rules/0/host
value: "dev.memorizer.fullstack.pw"
target:
kind: Ingress
name: memorizer
Loading