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 6 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.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Let's put this under the SDK section instead of the getting started section.


1. Go installed (at least version 1.18)
2. DiceDB server running locally
3. Basic familiarity with Go and DiceDB
Copy link
Collaborator

Choose a reason for hiding this comment

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

We can remove this.

Suggested change
3. Basic familiarity with Go and DiceDB

2. DiceDB server running locally
3. Basic familiarity with Go and DiceDB

## Environment setup
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
## Environment setup
## Setup


## Environment setup

Refer to [DiceDB Installation Guide](https://dicedb.io/get-started/installation/) to get your DiceDB server up and running with a simple Docker command.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Prefer relative URLs instead of absolute URLs. This would mean that if the docs move to a new domain in the future, we wouldn't have to manually update all the links.

Suggested change
Refer to [DiceDB Installation Guide](https://dicedb.io/get-started/installation/) to get your DiceDB server up and running with a simple Docker command.
Refer to [DiceDB Installation Guide](/get-started/installation) to get your DiceDB server up and running with a simple Docker command.


1. Clone the repository
```bash
git clone https://github.com/Prachi-Jamdade/url-shortner-go-dicedb
Copy link
Collaborator

Choose a reason for hiding this comment

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

Two things,

  1. The examples should allow users to have a super minimal setup to try stuff out. Ideally, they should not require much setup so they don't need to clone repositories to get started.
  2. We shouldn't be linking personal repositories in the official docs. If you would like to make the code available to the users you can add it under the examples directory of this repo.

Comment on lines 147 to 167
func FindURLByID(id string) (models.URL, error) {
ctx := context.Background()

// Retrieve the serialized URL data from DiceDB
stringCmd := db.Get(ctx, id)
urlData, err := stringCmd.Result()
if err != nil {
if err == dicedb.Nil {
return models.URL{}, errors.New("URL not found")
}
return models.URL{}, fmt.Errorf("failed to retrieve URL: %w", err)
}

// Deserialize the JSON data back into the URL struct
var url models.URL
err = json.Unmarshal([]byte(urlData), &url)
if err != nil {
return models.URL{}, fmt.Errorf("failed to decode URL data: %w", err)
}
return url, nil
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Based on above comments this can be simplified down to just a couple of lines of code. All it needs to do is lookup keys by short URL.

Comment on lines 185 to 209
func CreateShortURLService(longURL string) (string, error) {
id := uuid.New().String()[:8] // Shorten ID for URL

url := models.URL{
ID: id,
LongURL: longURL,
ShortURL: "http://localhost:8080/" + id,
}

if err := repository.SaveURL(url); err != nil {
fmt.Println(err)
return "", err
}

return url.ShortURL, nil
}

func GetOriginalURLService(id string) (string, error) {
url, err := repository.FindURLByID(id)
if err != nil {
return "", err
}

return url.LongURL, nil
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need to have "services" here. Just direct SDK calls from within the go application are enough.

Comment on lines 268 to 281
package utils

import (
"github.com/gin-gonic/gin"
)

func RespondWithError(c *gin.Context, code int, message string) {
c.JSON(code, gin.H{"error": message})
}

func RespondWithJSON(c *gin.Context, code int, payload interface{}) {
c.JSON(code, payload)
}
```
Copy link
Collaborator

Choose a reason for hiding this comment

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

no need to have this in a separate package/file. the actual code these functions encapsulate is simpler to understand at first glance as compared to hiding them behind an abstraction

}
```

6. `main.go`: Sets up the Gin (a HTTP Web Framework) router and registers routes. This is the entry point of the application.
Copy link
Collaborator

Choose a reason for hiding this comment

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

Please have the entire code for the application contained within main.go.

Comment on lines 301 to 306
## Conclusion

This project demonstrates how to set up a simple yet functional API for URL shortening, which can be expanded further with additional features or integrated into a larger application. With Go’s performance and DiceDB’s efficiency, this offers a lightweight solution for URL management.

Find the complete code for this example on [Github](https://github.com/Prachi-Jamdade/url-shortner-go-dicedb).

Copy link
Collaborator

Choose a reason for hiding this comment

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

We can remove this.

Suggested change
## Conclusion
This project demonstrates how to set up a simple yet functional API for URL shortening, which can be expanded further with additional features or integrated into a larger application. With Go’s performance and DiceDB’s efficiency, this offers a lightweight solution for URL management.
Find the complete code for this example on [Github](https://github.com/Prachi-Jamdade/url-shortner-go-dicedb).

@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 ?

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