updates distributed service

This commit is contained in:
Zheyuan Wu
2025-10-24 15:58:12 -05:00
parent d8096410af
commit 05d5b92255
12 changed files with 224 additions and 19 deletions

View File

@@ -20,3 +20,11 @@ _Warning: This project is not suitable for free Vercel plan. There is insufficie
### Deploying to Cloudflare Pages
[![Deploy to Cloudflare Workers](https://deploy.workers.cloudflare.com/button?paid=true)](https://deploy.workers.cloudflare.com/?url=https://github.com/Trance-0/Notechondria)
### Deploying as separated docker services
Considering the memory usage for this project, it is better to deploy it as separated docker services.
```bash
docker-compose up -d -f docker/docker-compose.yaml
```

View File

@@ -0,0 +1,110 @@
# Math4201 Topology I (Lecture 24)
## Connected and compact spaces
### Connectedness
Recall from example last lecture, there exists a connected space but not path-connected space.
#### Lemma on connectedness
Let $X$ be a topological space and $A\subseteq X$ is a connected subspace. If $B\subseteq X$ satisfies $A\subseteq B\subseteq \overline{A}$, then $B$ is connected. In particular, $\overline{A}$ is connected.
<details>
<summary>Proof</summary>
Assume that $B$ is not connected. In particular, there are open subspaces $U$ and $V$ of $X$ such that $U\cap B, V\cap B$ is a separation of $B$.
Take $U\cap A, V\cap A$, we show that this gives a separation of $A$.
(i) Since $U,V$ are open, $U\cap A, V\cap A$ are open in $A$.
(ii) Since $(U\cap B)\cap (V\cap B)=\emptyset$, $(U\cap A)\cap (V\cap A)=\emptyset$.
(iii) Since $(U\cap B)\cup (V\cap B)=B$, any point in $B$ is in either $U\cap B$ or $V\cap B$.
Since $A\subseteq B$, $(U\cap A)\cup (V\cap A)=A$.
(iv) $U\cap A$ and $V\cap A$ is nonempty by assumption $U\cap B$ is nonempty and contains $x\in B\cap U\subseteq \overline{A}$. So any open neighborhood of $x$ have non-empty intersection $x'\in A$, so $x'\in U\cap A$ and $U\cap A$ is nonempty. Similarly, $V\cap A$ is nonempty.
So $U\cap A$ and $V\cap A$ is a separation of $A$, which contradicts the assumption that $A$ is connected.
Therefore, $B$ is connected.
</details>
#### Topologists' sine curve
Let $A=\{(x,y)\in \mathbb{R}^2\mid y=\sin(1/x), x>0\}$. Then $A$ is connected, and also path-connected.
$$
\gamma(t) = (t, \sin(1/t)) \text{ for } t\in (0,1]
$$
However, take $\overline{A}=A\cup \{0\}\times [-1,1]$. Then $\overline{A}$ is not path-connected but connected.
<details>
<summary>Proof that topologists' sine curve is not path-connected</summary>
We want to show $X=\overline{A}$ has no continuous path
$$
\gamma:([0,1])\to X
$$
such that $\gamma(0)=(0,0)$ and $\gamma(1)=(1,\sin(1))$.
If there exists such a path, let $t_0\in [0,1]$ be defined as
$$
t_0=\sup\{t\in [0,1]\mid \gamma(t)=(0,x), x\in [0,1]\}
$$
By the assumption on $t_0$, we can find a sequence $\{t_n\}_{n\in\mathbb{N}_+}\subseteq A$ such that $t_n\to t$.
By continuity of $\gamma$, we have $\gamma(t_n)\to \gamma(t_0)$, $(0,y_n)\to (0,y_0)$.
Now focus on the restriction of $\gamma$ to $[t_0,1]$, $\gamma:[t_0,1]\to X$, $\gamma(t_0)=(0,y_0)$, $\gamma(1)=(1,\sin(1))$.
$t\in (t_0,1]$, then $\gamma(t)\in$ graph of $y=\sin(1/x)$.
Consider $\pi$ be the projection map to $x$-axis, $\pi\circ \gamma:[t_0,1]\to \mathbb{R}$, $\pi\circ \gamma(t_0)=0$ and $\pi\circ \gamma(1)=1$.
In particular, there is a sequence $s_n\in [t_0,1]$ such that $s_n\to t_0$ and $\pi\circ \gamma(s_n)=\frac{1}{n\pi+\frac{\pi}{2}}$. (using intermediate value theorem)
Then $\gamma(s_n)=(\frac{1}{n\pi},\sin(n\pi+\frac{\pi}{2}))=(\frac{1}{n\pi},(-1)^n)$.
Since as $s_n\to t_0$, and $\gamma$ is continuous, then we get a contradiction that the sequence $\gamma(s_n)$ should converge to $(0,t_0)$ where it is not.
</details>
### Compactness
Motivation: in real numbers.
#### Extreme value theorem
Let $f:[a,b]\to \mathbb{R}$ be continuous. Then there are $x_m,x_M\in [a,b]$ such that $f(x_m)\leq f(x)\leq f(x_M)$ for all $x\in [a,b]$.
#### Definition of cover
Let $X$ be a topological space. A covering of $X$ is a collection of subsets of $X$ that covers $X$.
$$
\{U_\alpha\}_{\alpha\in I}
$$
such that $X=\bigcup_{\alpha\in I} U_\alpha$.
An open cover of $X$ is a covering of $X$ such that each $U_\alpha$ is open.
#### Definition of compact space
A topological space $X$ is compact if for any open covering $\{U_\alpha\}_{\alpha\in I}$ of $X$, there exists a finite subcovering $\{U_{\alpha_i}\}_{i=1}^n$ such that $X=\bigcup_{i=1}^n U_{\alpha_i}$.
<details>
<summary>Example of non-compact space</summary>
Consider the interval $(0,1]$, the open covering $(\frac{1}{n},1]$ open in $(0,1]$, $\{(\frac{1}{n},1]\}_{n\in \mathbb{N}_+}$ has no finite subcovering.
</details>

View File

@@ -27,4 +27,5 @@ export default {
Math4201_L21: "Topology I (Lecture 21)",
Math4201_L22: "Topology I (Lecture 22)",
Math4201_L23: "Topology I (Lecture 23)",
Math4201_L24: "Topology I (Lecture 24)",
}

View File

@@ -1,4 +1,11 @@
export default {
/**
* Do not remove the labels "Math Courses Start"
* and "Math Courses End" and "CSE Courses Start" and "CSE Courses End"
* or the separated builds will not work.
*
* WE USE THESE LABELS TO BUILD THE SEPARATED WEBSITES FOR MATH AND CSE COURSES.
*/
menu: {
title: 'Home',
type: 'menu',
@@ -17,6 +24,7 @@ export default {
}
},
},
/* Math Courses Start */
Math3200: {
type: 'page',
theme:{
@@ -59,6 +67,8 @@ export default {
timestamp: true,
}
},
/* Math Courses End */
/* CSE Courses Start */
CSE332S: {
title: 'CSE332S',
type: 'page',
@@ -108,6 +118,7 @@ export default {
timestamp: true,
}
},
/* CSE Courses End */
Swap: {
display: 'hidden',
theme:{

View File

@@ -1,4 +1,4 @@
# Dockerfile for CSE folders
# Dockerfile for Math folders
# Source: https://github.com/vercel/next.js/blob/canary/examples/with-docker-multi-env/docker/production/Dockerfile
# syntax=docker.io/docker/dockerfile:1
@@ -28,10 +28,21 @@ FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN ls -la
# 2.1 Remove unnecessary files for build with title not starting with CSE
RUN find ./content -type d -not -name "CSE*" -exec rm -rf {} +
RUN find ./public -type f -not -name "*.md" -exec rm -rf {} +
# 2.1 Remove unnecessary files for build with title starting with CSE
RUN cd ./content && find . -maxdepth 1 -type d -name "Math*" -exec rm -rf {} +
RUN cd ./public && find . -maxdepth 1 -type d -name "Math*" -exec rm -rf {} +
# 2.1.1 Check the updated folders
RUN cd ./content && ls -la
RUN cd ./public && ls -la
# 2.2 Update the _meta.js files in the content folder
RUN sed -i '/\/\* Math Courses Start \*\//,/\/\* Math Courses End \*\//d' ./content/_meta.js
# 2.2.1 Check the updated _meta.js file
RUN cat ./content/_meta.js
# This will do the trick, use the corresponding env file for each environment.
# COPY .env.production.sample .env.production
@@ -55,8 +66,8 @@ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
EXPOSE 4201
ENV PORT=3000
ENV PORT=4201
CMD HOSTNAME="0.0.0.0" node server.js

1
docker/cse/test-build.sh Normal file
View File

@@ -0,0 +1 @@
sudo docker build -t trance-0/notenextra-cse:v1.2.0 -f ./docker/cse/Dockerfile --no-cache --progress=plain .

View File

@@ -0,0 +1,30 @@
services:
# you may need to update relative directories if you move this file
# default created directories is /docker/docker-compose.yaml
notenextra-math:
build:
context: ../
dockerfile: ./docker/math/Dockerfile
tags:
- trance0/notenextra-math:latest
restart: on-failure:5
ports:
- 13001:4201
notenextra-cse:
build:
context: ../
dockerfile: ./docker/cse/Dockerfile
tags:
- trance0/notenextra-cse:latest
restart: on-failure:5
ports:
- 13002:4202
nginx:
image: nginx:latest
ports:
- 13000:80
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
depends_on:
- notenextra-math
- notenextra-cse

View File

@@ -28,12 +28,21 @@ FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN ls -la
# 2.1 Remove unnecessary files for build with title starting with CSE
RUN cd /app/content
RUN find . -maxdepth 1 -type d -name "CSE*" -delete
RUN cd /app/public
RUN find . -maxdepth 1 -type d -name "CSE*" -delete
RUN cd ./content && find . -maxdepth 1 -type d -name "CSE*" -exec rm -rf {} +
RUN cd ./public && find . -maxdepth 1 -type d -name "CSE*" -exec rm -rf {} +
# 2.1.1 Check the updated folders
RUN cd ./content && ls -la
RUN cd ./public && ls -la
# 2.2 Update the _meta.js files in the content folder
RUN sed -i '/\/\* CSE Courses Start \*\//,/\/\* CSE Courses End \*\//d' ./content/_meta.js
# 2.2.1 Check the updated _meta.js file
RUN cat ./content/_meta.js
# This will do the trick, use the corresponding env file for each environment.
# COPY .env.production.sample .env.production

View File

@@ -0,0 +1 @@
sudo docker build -t trance-0/notenextra-math:v1.2.0 -f ./docker/math/Dockerfile --no-cache --progress=plain .

23
docker/nginx.conf Normal file
View File

@@ -0,0 +1,23 @@
# Example for conf.d/default.conf
server {
listen 80;
server_name localhost;
location /Math* {
proxy_pass http://notenextra-math:4201;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /CSE* {
proxy_pass http://notenextra-cse:4202;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

View File

@@ -1,8 +1,8 @@
/** @type {import('next-sitemap').IConfig} */
export default {
siteUrl: 'https://notenextra.trance-0.com',
changefreq: 'weekly',
priority: '0.5',
generateIndexSitemap: false,
exclude: ['/icon.svg']
}
module.exports = {
siteUrl: 'https://notenextra.trance-0.com',
changefreq: 'daily',
priority: '0.5',
generateIndexSitemap: false,
exclude: ['/icon.svg']
}

View File

@@ -26,8 +26,8 @@ export default bundleAnalyzer(withNextra({
},
experimental: {
webpackMemoryOptimizations: true,
staticGenerationMaxConcurrency: 2, // try 13
staticGenerationMinPagesPerWorker: 1 // keep small
staticGenerationMaxConcurrency: 2, // try 13, default is 8
staticGenerationMinPagesPerWorker: 1 // keep small, default is 25
}
}))