Skip to content

Commit

Permalink
Merge pull request #1178 from gofr-dev/release/v1.26.0
Browse files Browse the repository at this point in the history
Release/v1.26.0
  • Loading branch information
Umang01-hash authored Nov 7, 2024
2 parents ca59aa0 + c087a25 commit f87b8c1
Show file tree
Hide file tree
Showing 66 changed files with 7,158 additions and 32 deletions.
82 changes: 80 additions & 2 deletions docs/advanced-guide/using-publisher-subscriber/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ scaled and maintained according to its own requirement.

## Design choice

In GoFr application if a user wants to use the Publisher-Subscriber design, it supports two message brokers—Apache Kafka
and Google PubSub.
In GoFr application if a user wants to use the Publisher-Subscriber design, it supports several message brokers,
including Apache Kafka, Google PubSub, MQTT, and NATS JetStream.
The initialization of the PubSub is done in an IoC container which handles the PubSub client dependency.
With this, the control lies with the framework and thus promotes modularity, testability, and re-usability.
Users can do publish and subscribe to multiple topics in a single application, by providing the topic name.
Expand Down Expand Up @@ -175,6 +175,84 @@ docker run -d \
eclipse-mosquitto:latest
```
> **Note**: find the default mosquitto config file {% new-tab-link title="here" href="https://github.com/eclipse/mosquitto/blob/master/mosquitto.conf" /%}
### NATS JetStream

NATS JetStream is supported as an external pubsub provider, meaning if you're not using it, it won't be added to your binary.

**References**

https://docs.nats.io/
https://docs.nats.io/nats-concepts/jetstream
https://docs.nats.io/using-nats/developer/connecting/creds

#### Configs
```dotenv
PUBSUB_BACKEND=NATS
PUBSUB_BROKER=nats://localhost:4222
NATS_STREAM=mystream
NATS_SUBJECTS=orders.*,shipments.*
NATS_MAX_WAIT=5s
NATS_MAX_PULL_WAIT=500ms
NATS_CONSUMER=my-consumer
NATS_CREDS_FILE=/path/to/creds.json
```

#### Setup

To set up NATS JetStream, follow these steps:

1. Import the external driver for NATS JetStream:

```bash
go get gofr.dev/pkg/gofr/datasources/pubsub/nats
```

2. Use the `AddPubSub` method to add the NATS JetStream driver to your application:

```go
app := gofr.New()

app.AddPubSub(nats.New(nats.Config{
Server: "nats://localhost:4222",
Stream: nats.StreamConfig{
Stream: "mystream",
Subjects: []string{"orders.*", "shipments.*"},
},
MaxWait: 5 * time.Second,
MaxPullWait: 500 * time.Millisecond,
Consumer: "my-consumer",
CredsFile: "/path/to/creds.json",
}))
```

#### Docker setup
```shell
docker run -d \
--name nats \
-p 4222:4222 \
-p 8222:8222 \
-v <path-to>/nats.conf:/nats/config/nats.conf \
nats:2.9.16
```

#### Configuration Options

| Name | Description | Required | Default | Example |
|------|-------------|----------|---------|---------|
| `PUBSUB_BACKEND` | Set to "NATS" to use NATS JetStream as the message broker | Yes | - | `NATS` |
| `PUBSUB_BROKER` | NATS server URL | Yes | - | `nats://localhost:4222` |
| `NATS_STREAM` | Name of the NATS stream | Yes | - | `mystream` |
| `NATS_SUBJECTS` | Comma-separated list of subjects to subscribe to | Yes | - | `orders.*,shipments.*` |
| `NATS_MAX_WAIT` | Maximum wait time for batch requests | No | - | `5s` |
| `NATS_MAX_PULL_WAIT` | Maximum wait time for individual pull requests | No | 0 | `500ms` |
| `NATS_CONSUMER` | Name of the NATS consumer | No | - | `my-consumer` |
| `NATS_CREDS_FILE` | Path to the credentials file for authentication | No | - | `/path/to/creds.json` |

#### Usage

When subscribing or publishing using NATS JetStream, make sure to use the appropriate subject name that matches your stream configuration.
For more information on setting up and using NATS JetStream, refer to the official NATS documentation.

### Azure Eventhub
GoFr supports eventhub starting gofr version v1.22.0.
Expand Down
9 changes: 7 additions & 2 deletions docs/quick-start/connecting-mysql/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ DB_PASSWORD=root123
DB_NAME=test_db
DB_PORT=3306
DB_DIALECT=mysql
DB_CHARSET=
# DB_CHARSET: The character set for database connection (default: utf8).
# The `DB_CHARSET` defaults to utf8, but setting it to utf8mb4 is recommended if you need full Unicode support,
# including emojis and special characters.
```

Now in the following example, we'll store customer data using **POST** `/customer` and then use **GET** `/customer` to retrieve the same.
Expand All @@ -50,7 +55,7 @@ import (
"errors"

"github.com/redis/go-redis/v9"

"gofr.dev/pkg/gofr"
)

Expand Down Expand Up @@ -105,7 +110,7 @@ func main() {
// return the customer
return customers, nil
})

app.Run()
}
```
Expand Down
24 changes: 23 additions & 1 deletion docs/references/configs/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ This document lists all the configuration options supported by the GoFr framewor

- PUBSUB_BACKEND
- Pub/Sub message broker backend
- kafka, google, mqtt
- kafka, google, mqtt, nats

{% /table %}

Expand Down Expand Up @@ -338,3 +338,25 @@ This document lists all the configuration options supported by the GoFr framewor
- Sends regular messages to check the link is active. May not work as expected if handling func is blocking execution

{% /table %}

**NATS JetStream**

{% table %}

- Name
- Description
- Default Value

---

- NATS_SERVER
- URL of the NATS server
- nats://localhost:4222

---

- NATS_CREDS_FILE
- File containing the NATS credentials
- creds.json

{% /table %}
44 changes: 44 additions & 0 deletions examples/sample-cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package main

import (
"fmt"
"time"

"gofr.dev/pkg/gofr"
"gofr.dev/pkg/gofr/cmd/terminal"
)

func main() {
Expand All @@ -23,6 +25,48 @@ func main() {
return fmt.Sprintf("Hello %s!", c.Param("name")), nil
})

app.SubCommand("spinner", spinner)

app.SubCommand("progress", progress)

// Run the command-line application
app.Run()
}

func spinner(ctx *gofr.Context) (interface{}, error) {
// initialize the spinner
sp := terminal.NewDotSpinner(ctx.Out)
sp.Spin(ctx)

defer sp.Stop()

select {
case <-ctx.Done():
return nil, ctx.Err()
case <-time.After(2 * time.Second):
}

return "Process Complete", nil
}

func progress(ctx *gofr.Context) (interface{}, error) {
p, err := terminal.NewProgressBar(ctx.Out, 100)
if err != nil {
ctx.Warn("error initializing progress bar, err : %v", err)
}

for i := 1; i <= 100; i++ {
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-time.After(50 * time.Millisecond):
// do a time taking process or compute a small subset of a bigger problem,
// this could be processing batches of a data set.

// increment the progress to display on the progress bar.
p.Incr(int64(1))
}
}

return "Process Complete", nil
}
63 changes: 62 additions & 1 deletion examples/sample-cmd/main_test.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
package main

import (
"context"
"os"
"strings"
"testing"

"github.com/stretchr/testify/assert"

"gofr.dev/pkg/gofr"
"gofr.dev/pkg/gofr/cmd"
"gofr.dev/pkg/gofr/cmd/terminal"
"gofr.dev/pkg/gofr/container"
"gofr.dev/pkg/gofr/logging"
"gofr.dev/pkg/gofr/testutil"
)

Expand Down Expand Up @@ -44,3 +49,59 @@ func TestCMDRunWithParams(t *testing.T) {
assert.Contains(t, output, expResp, "TEST[%d], Failed.\n", i)
}
}

func TestCMDRun_Spinner(t *testing.T) {
os.Args = []string{"command", "spinner"}
output := testutil.StdoutOutputForFunc(main)

// contains the spinner in the correct order
assert.Contains(t, output, "\r\r\r\r\r⡿")
// contains the process completion message
assert.Contains(t, output, "Process Complete\n")
}

func TestCMDRun_SpinnerContextCancelled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()

// add an already canceled context
res, err := spinner(&gofr.Context{
Context: ctx,
Request: cmd.NewRequest([]string{"command", "spinner"}),
Container: nil,
Out: terminal.New(),
})

assert.Empty(t, res)
assert.ErrorIs(t, err, context.Canceled)
}

func TestCMDRun_Progress(t *testing.T) {
os.Args = []string{"command", "progress"}

output := testutil.StdoutOutputForFunc(main)

assert.Contains(t, output, "\r1.000%")
assert.Contains(t, output, "\r20.000%")
assert.Contains(t, output, "\r50.000%")
assert.Contains(t, output, "\r100.000%")
assert.Contains(t, output, "Process Complete\n")
}

func TestCMDRun_ProgressContextCancelled(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
cancel()

// add an already canceled context
res, err := progress(&gofr.Context{
Context: ctx,
Request: cmd.NewRequest([]string{"command", "spinner"}),
Container: &container.Container{
Logger: logging.NewMockLogger(logging.ERROR),
},
Out: terminal.New(),
})

assert.Empty(t, res)
assert.ErrorIs(t, err, context.Canceled)
}
35 changes: 35 additions & 0 deletions examples/using-add-filestore/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Add FileStore Example

This GoFr example demonstrates a CMD application that can be used to interact with a remote file server using FTP or SFTP protocol

### Setting up an FTP server in local machine
- https://security.appspot.com/vsftpd.html
- https://pypi.org/project/pyftpdlib/

Choose a library listed above and follow their respective documentation to configure an FTP server in your local machine and replace the configs/env file with correct HOST,USER_NAME,PASSWORD,PORT and REMOTE_DIR_PATH details.

### To run the example use the commands below:
To print the current working directory of the configured remote file server
```console
go run main.go pwd
```
To get the list of all directories or files in the given path of the configured remote file server

```
go run main.go ls -path=/
```
To grep the list of all files and directories in the given path that is matching with the keyword provided

```
go run main.go grep -keyword=fi -path=/
```

To create a file in the current working directory with the provided filename
```
go run main.go createfile -filename=file.txt
```

To remove the file with the provided filename from the current working directory
```
go run main.go rm -filename=file.txt
```
5 changes: 5 additions & 0 deletions examples/using-add-filestore/configs/.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
HOST=localhost
USER_NAME=anonymous
PASSWORD=test
PORT=21
REMOTE_DIR_PATH=/
Loading

0 comments on commit f87b8c1

Please sign in to comment.