Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(memorystore): added valkey leaderboard demo application #10007

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 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
94 changes: 94 additions & 0 deletions memorystore/valkey/leaderboard/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Leaderboard

This demo shows how to use Valkey as an in-memory cache to accelerate data retrieval in a leaderboard application. By storing top scores in Valkey, the application can quickly retrieve the top entries without having to query the database.

## Running the application locally

### 1. Run your database locally. You can download and install PostgresSQL via this [link](https://www.postgresql.org/download/)

### 2. Run your Valkey server locally. You can download and install Valkey via this [link](https://valkey.io/download/)

### 3. Ensure that you have a user created called `postgres`

```bash
createuser -s postgres
```

### 4. Next, create the required database tables

```bash
psql -U postgres -d postgres -f ./app/init.sql
```

### 5. Run the application

```bash
mvn clean spring-boot:run
```

### 6. Navigate to the web url `http://localhost:8080` to view your application

## How to run the application locally (via Docker)

You can use [docker compose](https://docs.docker.com/compose/install/) to run the app locally. Run the following:

```bash
cd app
docker-compose up --build
```

You can also run with sample leaderboard data. Run the following:

```bash
cd sample-data
docker-compose up --build
```

## How to deploy the application to Google Cloud

1. You can use [Terraform](https://learn.hashicorp.com/tutorials/terraform/install-cli) to deploy the infrastructure to Google Cloud. Run the following:

```bash
cd app
terraform init
terraform apply
```

It should fail to ceate the Google Cloud Run service, but don't worry, we'll fix that in the next series of steps. The message you get might look like this:

```
Error waiting to create Service: Error waiting for Creating Service: Error code 13, message: Revision 'leaderboard-app-service-00001-9zj' is not ready and cannot serve traffic. Image 'gcr.io/cloudannot serve traffic. Image 'gcr.io/cloud-memorystore-demos/leaderboard-app:latest' not found.
```

2. Once the infrastructure is created, you'll need to run the `init.sql` script in the Cloud SQL instance to create the necessary tables. You can use the Cloud Shell to do this. Run the following command in the Cloud Shell:

```bash
gcloud sql connect <instance_name> --database=leaderboard-app-db --user=admin # The admin and database were created in the Terraform script
```

Note: Ensure that the instance name is the same as the one you used in the Terraform script.

a. When prompted to enable the Cloud SQL Admin API, type `Y` and press `Enter`.
b. When prompted to enter the password, type the password you set in the Terraform script and press `Enter`.
c. Once you're connected to the Cloud SQL instance, run the following command to run the `init.sql` script:

```sql
\i init.sql
```

3. Finally, redeploy the Cloud Run service using the local source code. Run the following command:

```bash
gcloud run deploy <instance_name> \
--source=. \
--region=<region>
```

Note: Ensure that the instance name and region are the same as the ones you used in the Terraform script.

Now you should have the application running on Google Cloud.

### Endpoints

- `GET /api/leaderboard`: By default, this endpoint returns the top X entries in the leaderboard. Optionally, a parameter `position` can be provided to return the leaderboard starting from that position.
- `POST /api/leaderboard`: This endpoint creates or updates a leaderboard entry with a given username and score.
92 changes: 92 additions & 0 deletions memorystore/valkey/leaderboard/app/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
##############################
## Java
##############################
.mtj.tmp/
*.class
*.jar
*.war
*.ear
*.nar
hs_err_pid*

##############################
## Maven
##############################
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
pom.xml.bak
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.mvn/wrapper/maven-wrapper.jar

##############################
## Gradle
##############################
bin/
build/
.gradle
.gradletasknamecache
gradle-app.setting
!gradle-wrapper.jar

##############################
## IntelliJ
##############################
out/
.idea/
.idea_modules/
*.iml
*.ipr
*.iws

##############################
## Eclipse
##############################
.settings/
bin/
tmp/
.metadata
.classpath
.project
*.tmp
*.bak
*.swp
*~.nib
local.properties
.loadpath
.factorypath

##############################
## NetBeans
##############################
nbproject/private/
build/
nbbuild/
dist/
nbdist/
nbactions.xml
nb-configuration.xml

##############################
## Visual Studio Code
##############################
.vscode/
.code-workspace

##############################
## OS X
##############################
.DS_Store

##############################
## Terraform
##############################
.terraform/
.terraform.lock.hcl
terraform.tfstate
terraform.tfstate.backup
24 changes: 24 additions & 0 deletions memorystore/valkey/leaderboard/app/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Use an OpenJDK base image
FROM openjdk:17-jdk-slim

# Install Maven for building the project
RUN apt-get update && apt-get install -y maven

# Set the working directory
WORKDIR /app

# Copy Maven project files
COPY pom.xml ./
COPY src ./src

# Build the project
RUN mvn clean package -DskipTests

# Copy the built JAR file to the container
RUN cp target/app-1.0-SNAPSHOT.jar app.jar

# Expose the application port
EXPOSE 8080

# Run the application
CMD ["java", "-jar", "app.jar"]
51 changes: 51 additions & 0 deletions memorystore/valkey/leaderboard/app/docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: leaderboard-app

services:
valkey:
image: valkey/valkey:latest
ports:
- "6379:6379"
command: ["valkey-server", "--save", "60", "1", "--loglevel", "warning"]

postgres:
image: postgres:latest
container_name: postgres
ports:
- "5432:5432"
environment:
- POSTGRES_USER=admin
- POSTGRES_PASSWORD=password
- POSTGRES_DB=postgres
volumes:
- ./init.sql:/docker-entrypoint-initdb.d/init.sql

app:
build:
context: .
dockerfile: Dockerfile
container_name: java-app
ports:
- "8080:8080"
depends_on:
- valkey
- postgres
environment:
- VALKEY_HOST=valkey
- VALKEY_PORT=6379
- DB_URL=jdbc:postgresql://postgres:5432/postgres
- DB_USERNAME=admin
- DB_PASSWORD=password
11 changes: 11 additions & 0 deletions memorystore/valkey/leaderboard/app/init.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
CREATE TABLE leaderboard (
username VARCHAR(255) NOT NULL,
score DOUBLE PRECISION NOT NULL,
PRIMARY KEY (username)
);

-- Create an index to ensure efficient ordering by score (descending)
CREATE INDEX idx_leaderboard_score ON leaderboard (score DESC);

-- Create an index to ensure efficient ordering by score (ascending)
CREATE INDEX idx_leaderboard_score_asc ON leaderboard (score ASC);
Loading