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

feat: Add a tutorial example for URL Shortner built using DiceDB and Go #1259

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

Prachi-Jamdade
Copy link

This commit adds an example of how to integrate the DiceDB Go SDK for building a URL shortener application.

The tutorial walks through setting up a basic URL shortening service, providing -

  1. Instructions on creating short URLs
  2. Redirecting to the original URLs
  3. Storing data in DiceDB.

The application utilizes the Set and Get commands from DiceDB to store and retrieve shortened URLs, and the example is designed to help developers quickly understand and implement a URL shortener using DiceDB and Go.

Copy link
Collaborator

@JyotinderSingh JyotinderSingh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for contributing a tutorial for dicedb. It's a great way to help new users get started.

I have left some comments on this PR, please address them.

docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
docs/src/content/docs/get-started/url-shortner.mdx Outdated Show resolved Hide resolved
@Prachi-Jamdade
Copy link
Author

Hi @JyotinderSingh, I have addressed above mentioned review changes and pushed the code.

Please take a look at it.

Copy link

@everlearner everlearner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor comments in the shortener code.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: typo in directory name url-shortner

// Initialize DiceDB connection
func init() {
db = dicedb.NewClient(&dicedb.Options{
Addr: "localhost:7379",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get hostname and port from ENV variables?
Similar to:

dhost := "localhost"
if val := os.Getenv("DICEDB_HOST"); val != "" {
dhost = val
}
dport := "7379"
if val := os.Getenv("DICEDB_PORT"); val != "" {
dport = val
}

}

// Creates a short URL from a given long URL
func CreateShortURL(c *gin.Context) {
Copy link

@everlearner everlearner Nov 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
func CreateShortURL(c *gin.Context) {
func createShortURL(c *gin.Context) {

}

// Redirects to the original URL based on the short URL ID
func RedirectURL(c *gin.Context) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit:

Suggested change
func RedirectURL(c *gin.Context) {
func redirectURL(c *gin.Context) {

Comment on lines 40 to 41
requestBody.ID = shortID
requestBody.ShortURL = "http://localhost:8080/" + shortID

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to store ID and ShortURL in the struct?
Having just LongURL is sufficient?

The mapping b/w ID and LongURL is anyway stored in the DiceDB.

@JyotinderSingh
Copy link
Collaborator

Thanks for addressing the comments @Prachi-Jamdade. Could you please resolve comments by @everlearner as well?

@Prachi-Jamdade
Copy link
Author

Hey @JyotinderSingh, pushed the code addressing changes raised by @everlearner

Copy link

@everlearner everlearner left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making the changes.

@Prachi-Jamdade
Copy link
Author

Hey @JyotinderSingh, any update ?

@JyotinderSingh
Copy link
Collaborator

Hey @JyotinderSingh, any update ?

Will review soon

Copy link
Collaborator

@JyotinderSingh JyotinderSingh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for addressing the reviews so far @Prachi-Jamdade. Documentation is a critical aspect of any project, and needs to be extremely polished. Keeping that in mind I've suggested some improvements.

Comment on lines 10 to 11
1. Go installed (at least version 1.18)
2. DiceDB server running locally
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1. Go installed (at least version 1.18)
2. DiceDB server running locally
1. Go (version 1.18 or later): [Download Go](https://golang.org/dl/)
2. DiceDB: A DiceDB server running locally. Refer to the [DiceDB Installation Guide](https://github.com/DiceDB/dice/pull/1259/get-started/installation) if you haven't set it up yet.

Comment on lines 24 to 36
## DiceDB Commands Used

Here are the main DiceDB commands we’ll use to store and retrieve URLs.

1. `Set` Command: Stores a key-value pair in DiceDB.
Syntax - `Set(key, value, expiration)`
`key`: Unique identifier (e.g., short URL code)
`value`: The data to store (serialized JSON)
`expiration`: Optional; 0 means no expiration

2. `Get` Command: Retrieves the value associated with a key.
Syntax - `Get(key)`
`key`: The identifier for the data to retrieve.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## DiceDB Commands Used
Here are the main DiceDB commands we’ll use to store and retrieve URLs.
1. `Set` Command: Stores a key-value pair in DiceDB.
Syntax - `Set(key, value, expiration)`
`key`: Unique identifier (e.g., short URL code)
`value`: The data to store (serialized JSON)
`expiration`: Optional; 0 means no expiration
2. `Get` Command: Retrieves the value associated with a key.
Syntax - `Get(key)`
`key`: The identifier for the data to retrieve.
## Understanding DiceDB Commands
We'll use the following DiceDB commands:
### `SET` Command
Stores a key-value pair in DiceDB.
- **Syntax**: `SET key value [expiration]`
- `key`: Unique identifier (e.g., short URL code)
- `value`: Data to store (e.g., serialized JSON)
- `expiration`: Optional; time-to-live in seconds (use `0` for no expiration)
### `GET` Command
Retrieves the value associated with a key.
- **Syntax**: `GET key`
- `key`: Identifier for the data to retrieve

Syntax - `Get(key)`
`key`: The identifier for the data to retrieve.

## Code overview
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Code overview
## Writing the Code
Create a file named `main.go` and add the following code:

}
```

## Explanation of Key Parts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Explanation of Key Parts
## Explanation

Comment on lines 135 to 138
1. Database Initialization: The `init()` function sets up a DiceDB client to connect to `localhost:7379`.
2. `CreateShortURL` Endpoint: Handles the `/shorten` route. It generates a unique ID, constructs the short URL, serializes the URL data, and saves it in DiceDB.
3. `RedirectURL` Endpoint: Handles the `/:id` route. It retrieves the original URL by the short ID from DiceDB and redirects the user to it.
4. Starting the Server: The `main` function starts the Gin server on port `8080`.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should make use of subheadings to make this clearer. PTAL at the following approach to write this:

Suggested change
1. Database Initialization: The `init()` function sets up a DiceDB client to connect to `localhost:7379`.
2. `CreateShortURL` Endpoint: Handles the `/shorten` route. It generates a unique ID, constructs the short URL, serializes the URL data, and saves it in DiceDB.
3. `RedirectURL` Endpoint: Handles the `/:id` route. It retrieves the original URL by the short ID from DiceDB and redirects the user to it.
4. Starting the Server: The `main` function starts the Gin server on port `8080`.
### 1. Initialize the DiceDB Client
We set up the DiceDB client in the `init` function:
```go
db = dicedb.NewClient(&dicedb.Options{
Addr: "localhost:7379",
})
```
### 2. Create Short URL Endpoint
- **Input Validation**: Ensures the `long_url` field is present.
- **Short ID Generation**: Uses `uuid` to create a unique 8-character ID.
- **Data Serialization**: Converts the `URL` struct to JSON.
- **Data Storage**: Saves the JSON data in DiceDB with the `Set` command.
- **Response**: Returns the generated short URL.
### 3. Redirect to Original URL Endpoint
- **Data Retrieval**: Fetches the URL data from DiceDB using the `Get` command.
- **Data Deserialization**: Converts JSON back to the `URL` struct.
- **Redirection**: Redirects the user to the `LongURL`.
### 4. Start the Server
The `main` function sets up the routes and starts the server on port `8080`.

## Interacting with the application

1. Start DiceDB: Ensure DiceDB is running.
2. Test the API:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
2. Test the API:
## Testing the Application

Comment on lines 156 to 167
Send a POST request to `/shorten` with JSON body on Postman:
```
{
"long_url": "https://example.com"
}
```

OR

```curl
curl -X POST -H "Content-Type: application/json" -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Send a POST request to `/shorten` with JSON body on Postman:
```
{
"long_url": "https://example.com"
}
```
OR
```curl
curl -X POST -H "Content-Type: application/json" -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten
```
**Using `curl`:**
```bash
curl -X POST -H "Content-Type: application/json" -d '{"long_url": "https://example.com"}' http://localhost:8080/shorten
```
**Response:**
```json
{
"short_url": "http://localhost:8080/<short ID generated by the server>"
}
```

Comment on lines 170 to 176
Send a GET request to `/:id` with the short URL ID on Postman

OR

```curl
curl -L http://localhost:8080/{short_id}
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Send a GET request to `/:id` with the short URL ID on Postman
OR
```curl
curl -L http://localhost:8080/{short_id}
```
**Using `curl`:**
```bash
curl -L http://localhost:8080/abcd1234
```
**Using a Browser:**
Navigate to:
```
http://localhost:8080/abcd1234
```
You should be redirected to `https://example.com`.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file is not needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need such a detailed dockerfile, the following is fine:

# Build Stage
FROM golang:1.23 AS builder

WORKDIR /app

# Copy go.mod and go.sum to download dependencies
COPY go.mod go.sum ./
RUN go mod download

# Copy application source code and build
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o server .

# Runtime Stage
FROM alpine:latest

# Install runtime dependencies
RUN apk --no-cache add ca-certificates

# Copy the built application
WORKDIR /root/
COPY --from=builder /app/server .

# Expose the application port
EXPOSE 8080

# Start the application
CMD ["./server"]

Comment on lines 15 to 22
1. Refer to [DiceDB Installation Guide](get-started/installation) to get your DiceDB server up and running with a simple Docker command.
2. Initialize a New Go Project
3. Install DiceDB Go SDK and other required packges.
```bash
go get github.com/dicedb/dicedb-go
go get github.com/gin-gonic/gin
go get github.com/google/uuid
```
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
1. Refer to [DiceDB Installation Guide](get-started/installation) to get your DiceDB server up and running with a simple Docker command.
2. Initialize a New Go Project
3. Install DiceDB Go SDK and other required packges.
```bash
go get github.com/dicedb/dicedb-go
go get github.com/gin-gonic/gin
go get github.com/google/uuid
```
### 1. Install and Run DiceDB
Start a DiceDB server using Docker:
```bash
docker run -d -p 7379:7379 dicedb/dicedb
```
This command pulls the DiceDB Docker image and runs it, exposing it on port `7379`.
### 2. Initialize a New Go Project
Create a new directory for your project and initialize a Go module:
```bash
mkdir url-shortener
cd url-shortener
go mod init url-shortener
```
### 3. Install Required Packages
Install the DiceDB Go SDK and other dependencies:
```bash
go get github.com/dicedb/dicedb-go
go get github.com/gin-gonic/gin
go get github.com/google/uuid
```

@JyotinderSingh
Copy link
Collaborator

@Prachi-Jamdade hope you are doing well, are you actively working on this PR?

@Prachi-Jamdade
Copy link
Author

Hey @JyotinderSingh, yes I'll push changes by tomorrow morning.

Got stuck in end sem exams. I'll address them quickly.

@JyotinderSingh
Copy link
Collaborator

Hey @JyotinderSingh, yes I'll push changes by tomorrow morning.

Got stuck in end sem exams. I'll address them quickly.

Thanks for the update! No rush.

@Prachi-Jamdade
Copy link
Author

Hey @JyotinderSingh, addressed your changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants