-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Add `cluster-creator` container for cluster creation automation. - Introduce `redis-insight` container. - Update and improve README.md. - Enable `strict` mode in `tsconfig.json`. - Set up a Development Container. - Incorporate additional timezones for balanced cluster node utilization. - Relocate links from header to sidebar. - Make route an optional catch-all.
- Loading branch information
1 parent
21d2e90
commit 1ef74bd
Showing
9 changed files
with
277 additions
and
110 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the | ||
// README at: https://github.com/devcontainers/templates/tree/main/src/docker-in-docker | ||
{ | ||
"name": "Docker in Docker", | ||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile | ||
"image": "mcr.microsoft.com/devcontainers/base:bullseye", | ||
|
||
"features": { | ||
"ghcr.io/devcontainers/features/docker-in-docker:2": { | ||
"version": "latest", | ||
"enableNonRootDocker": "true", | ||
"moby": "true" | ||
}, | ||
"ghcr.io/devcontainers/features/node:1": {} | ||
} | ||
|
||
// Use 'forwardPorts' to make a list of ports inside the container available locally. | ||
// "forwardPorts": [], | ||
|
||
// Use 'postCreateCommand' to run commands after the container is created. | ||
// "postCreateCommand": "docker --version", | ||
|
||
// Configure tool-specific properties. | ||
// "customizations": {}, | ||
|
||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root. | ||
// "remoteUser": "root" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# To get started with Dependabot version updates, you'll need to specify which | ||
# package ecosystems to update and where the package manifests are located. | ||
# Please see the documentation for more information: | ||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates | ||
# https://containers.dev/guide/dependabot | ||
|
||
version: 2 | ||
updates: | ||
- package-ecosystem: "devcontainers" | ||
directory: "/" | ||
schedule: | ||
interval: weekly |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,52 +1,81 @@ | ||
# Next.js Redis Cluster Cache Integration Example | ||
|
||
Run docker compose to start redis locally | ||
This example demonstrates how to integrate a Redis Cluster Cache with a Next.js application. | ||
|
||
``` | ||
docker-compose up -d | ||
``` | ||
## Prerequisites | ||
|
||
open redis-1 terminal and create the cluster | ||
- **Debian-based OS**: Ensure your operating system is Debian-based (e.g., Ubuntu, Debian). | ||
- **Docker**: Ensure Docker is installed on your machine. | ||
- **Node.js**: Ensure Node.js (and npm) is installed on your machine. | ||
|
||
``` | ||
redis-cli --cluster create 172.38.0.11:6379 172.38.0.12:6379 172.38.0.13:6379 172.38.0.14:6379 172.38.0.15:6379 172.38.0.16:6379 --cluster-replicas 1 | ||
``` | ||
### Windows and MacOS Users | ||
|
||
type "yes" to apply the configuration. | ||
MacOS and Windows users can use [Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers) to run the example in a containerized environment. This project includes a `devcontainer.json` file that defines the container image and the necessary dependencies. | ||
|
||
verify that the cluster was created | ||
## Getting Started | ||
|
||
``` | ||
redis-cli -c | ||
cluster nodes | ||
``` | ||
### Step 1: Start Redis Using Docker Compose | ||
|
||
install next.js dependencies for the project | ||
To start Redis locally, run: | ||
|
||
```sh | ||
docker-compose up -d | ||
``` | ||
|
||
### Step 2: Install Project Dependencies | ||
|
||
Install the necessary Next.js dependencies: | ||
|
||
```sh | ||
npm i | ||
``` | ||
|
||
build next.js (will not use custom redis cache handler during build) | ||
### Step 3: Build the Next.js Application | ||
|
||
``` | ||
Build the Next.js application. Note that the custom Redis cache handler will not be used during the build process: | ||
|
||
```sh | ||
npm run build | ||
``` | ||
|
||
start next.js app | ||
### Step 4: Start the Next.js Application | ||
|
||
``` | ||
Start the Next.js application: | ||
|
||
```sh | ||
npm run start | ||
``` | ||
|
||
navigate to the local homepage [http://localhost:3000/cet](http://localhost:3000/cet) | ||
### Step 5: Access the Application | ||
|
||
Navigate to the local homepage in your browser: | ||
|
||
http://localhost:3000 | ||
|
||
Then navigate through the different timezones to see the cache in action. | ||
|
||
## Logging Configuration | ||
|
||
To remove logs, edit the package.json file by removing `NEXT_PRIVATE_DEBUG_CACHE=1`. | ||
|
||
to remove logs, remove NEXT_PRIVATE_DEBUG_CACHE=1 from package.json | ||
## Redis Cluster Management | ||
|
||
keep in mind that redis data will be stored in redis/node-X/data | ||
### Redis Data Storage | ||
|
||
to flush all the redis cluster use | ||
Redis data will be stored in `redis/node-X/data`. | ||
|
||
### Flushing the Redis Cluster | ||
|
||
To flush all data from the Redis cluster, use the following commands: | ||
|
||
Enter the Docker container: | ||
|
||
```sh | ||
docker exec -it cache-handler-redis-cluster-example-redis-1-1 /bin/bash | ||
``` | ||
|
||
Flush all Redis nodes: | ||
|
||
```sh | ||
redis-cli --cluster call --cluster-only-masters 172.38.0.11:6379 FLUSHALL | ||
``` | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
import { Suspense } from "react"; | ||
import Link from "next/link"; | ||
import { notFound } from "next/navigation"; | ||
import { CacheStateWatcher } from "../cache-state-watcher"; | ||
import { RevalidateFrom } from "../revalidate-from"; | ||
|
||
type TimeData = { | ||
unixtime: number; | ||
datetime: string; | ||
timezone: string; | ||
}; | ||
|
||
const API_BASE_URL = "https://worldtimeapi.org/api/timezone"; | ||
|
||
async function fetchTimezoneList(): Promise<string[]> { | ||
try { | ||
const response = await fetch(new URL(API_BASE_URL), { | ||
next: { revalidate: false }, | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error("Failed to fetch timezone list."); | ||
} | ||
|
||
const data: string[] = await response.json(); | ||
return data; | ||
} catch (error) { | ||
console.error(error); | ||
return []; | ||
} | ||
} | ||
|
||
async function fetchTimezoneData(zoneName: string): Promise<TimeData | null> { | ||
try { | ||
const response = await fetch(new URL(zoneName, API_BASE_URL), { | ||
next: { tags: ["time-data"] }, | ||
}); | ||
|
||
if (!response.ok) { | ||
throw new Error("Failed to fetch timezone data."); | ||
} | ||
|
||
const data: TimeData = await response.json(); | ||
|
||
return { | ||
timezone: data.timezone, | ||
datetime: data.datetime, | ||
unixtime: data.unixtime, | ||
}; | ||
} catch (error) { | ||
console.error(error); | ||
|
||
return null; | ||
} | ||
} | ||
|
||
const PRE_RENDERED_TIMEZONES = ["CET", "WET", "Africa/Abidjan"]; | ||
|
||
export const revalidate = 500; | ||
|
||
export async function generateStaticParams() { | ||
return PRE_RENDERED_TIMEZONES.map((timezone) => ({ | ||
timezone: timezone.split("/"), | ||
})); | ||
} | ||
|
||
type PageProps = { | ||
params: { timezone?: string[] }; | ||
}; | ||
|
||
export default async function Page({ params: { timezone: slug = [] } }: PageProps) { | ||
const timezoneList = await fetchTimezoneList(); | ||
|
||
const currentTimezone = slug.length ? slug.join("/") : PRE_RENDERED_TIMEZONES[0]; | ||
|
||
const timeData = await fetchTimezoneData(currentTimezone); | ||
|
||
if (!timeData) { | ||
notFound(); | ||
} | ||
|
||
return ( | ||
<> | ||
<aside className="sidebar"> | ||
{timezoneList.map(timezone => ( | ||
<Link key={timezone} className="sidebar-link" href={`/${timezone}`}> | ||
{timezone} | ||
</Link> | ||
))} | ||
</aside> | ||
<div className="main-content"> | ||
<main className="widget"> | ||
<div className="pre-rendered-at"> | ||
{timeData.timezone} Time {timeData.datetime} | ||
</div> | ||
<Suspense fallback={null}> | ||
<CacheStateWatcher | ||
revalidateAfter={revalidate * 1000} | ||
time={timeData.unixtime * 1000} | ||
/> | ||
</Suspense> | ||
<RevalidateFrom /> | ||
</main> | ||
</div> | ||
<footer className="footer"> | ||
<Link | ||
href={process.env.NEXT_PUBLIC_REDIS_INSIGHT_URL ?? "http://localhost:5540"} | ||
className="link" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
View RedisInsight ↪ | ||
</Link> | ||
</footer> | ||
</> | ||
); | ||
} |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.