Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
c8a566c
initial implementation for distributed and local storage rate limiters
Umang01-hash Sep 10, 2025
2048c54
fix linters and other errors in the initial implementation
Umang01-hash Sep 10, 2025
1d28995
fix bugs in the implementation after testing
Umang01-hash Sep 11, 2025
4e6ecd7
add documentation
Umang01-hash Sep 11, 2025
a651ea7
add test for local rate limiter implementation
Umang01-hash Sep 16, 2025
2b78265
Merge remote-tracking branch 'origin' into en/rate_limiter
Umang01-hash Sep 16, 2025
e826318
fix test
Umang01-hash Sep 16, 2025
51616b5
fix rate limiter concurrency test
Umang01-hash Sep 16, 2025
71d4f72
fix linters
Umang01-hash Sep 17, 2025
aae16f3
Merge remote-tracking branch 'origin' into en/rate_limiter
Umang01-hash Sep 25, 2025
a104474
make time window generic
Umang01-hash Sep 25, 2025
8c8b29b
update documentation
Umang01-hash Sep 25, 2025
1217084
Merge remote-tracking branch 'origin' into en/rate_limiter
Umang01-hash Sep 29, 2025
12bb728
resolve review comments
Umang01-hash Sep 29, 2025
51d3388
replace concrete rate limiter stores with interface
Umang01-hash Sep 29, 2025
29b15e2
Merge remote-tracking branch 'origin' into en/rate_limiter
Umang01-hash Sep 29, 2025
a90d0e2
add more tests
Umang01-hash Sep 30, 2025
fd7fe70
refactor implementation to unify the structs and remove duplicate codes
Umang01-hash Sep 30, 2025
815dec7
re-write tests
Umang01-hash Oct 3, 2025
82623af
Merge remote-tracking branch 'origin' into en/rate_limiter
Umang01-hash Oct 3, 2025
c54c78e
revert unwanted changes
Umang01-hash Oct 3, 2025
8e6f6ea
remove changes in interface of logger and metrics
Umang01-hash Oct 3, 2025
8568065
fix linters
Umang01-hash Oct 3, 2025
bb387ea
refactoring implementation
Umang01-hash Oct 3, 2025
f9f7b04
build(deps): update github.com/grpc-ecosystem/go-grpc-middleware to v2
Juneezee Oct 3, 2025
8bfd3fb
refactor(docs): replace {serviceName} placeholders with <SERVICE_NAME…
NishantRajZop Sep 27, 2025
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
46 changes: 23 additions & 23 deletions docs/advanced-guide/grpc/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ syntax = "proto3";
// Indicates the go package where the generated file will be produced
option go_package = "path/to/your/proto/file";

service {serviceName}Service {
rpc {serviceMethod} ({serviceRequest}) returns ({serviceResponse}) {}
service <SERVICE_NAME>Service {
rpc <SERVICE_METHOD> (<SERVICE_REQUEST>) returns (<SERVICE_RESPONSE>) {}
}
```

Expand All @@ -66,13 +66,13 @@ Users must define the type of message being exchanged between server and client,
procedure call. Below is a generic representation for services' gRPC messages type.

```protobuf
message {serviceRequest} {
message <SERVICE_REQUEST> {
int64 id = 1;
string name = 2;
// other fields that can be passed
}

message {serviceResponse} {
message <SERVICE_RESPONSE> {
int64 id = 1;
string name = 2;
string address = 3;
Expand All @@ -90,10 +90,10 @@ protoc \
--go_opt=paths=source_relative \
--go-grpc_out=. \
--go-grpc_opt=paths=source_relative \
{serviceName}.proto
<SERVICE_NAME>.proto
```

This command generates two files, `{serviceName}.pb.go` and `{serviceName}_grpc.pb.go`, containing the necessary code for performing RPC calls.
This command generates two files, `<SERVICE_NAME>.pb.go` and `<SERVICE_NAME>_grpc.pb.go`, containing the necessary code for performing RPC calls.

## Prerequisite: gofr-cli must be installed
To install the CLI -
Expand All @@ -109,15 +109,15 @@ go install gofr.dev/cli/gofr@latest
gofr wrap grpc server -proto=./path/your/proto/file
```

This command leverages the `gofr-cli` to generate a `{serviceName}_server.go` file (e.g., `customer_server.go`)
This command leverages the `gofr-cli` to generate a `<SERVICE_NAME>_server.go` file (e.g., `customer_server.go`)
containing a template for your gRPC server implementation, including context support, in the same directory as
that of the specified proto file.

**2. Modify the Generated Code:**

- Customize the `{serviceName}GoFrServer` struct with required dependencies and fields.
- Implement the `{serviceMethod}` method to handle incoming requests, as required in this usecase:
- Bind the request payload using `ctx.Bind(&{serviceRequest})`.
- Customize the `<SERVICE_NAME>GoFrServer` struct with required dependencies and fields.
- Implement the `<SERVICE_METHOD>` method to handle incoming requests, as required in this usecase:
- Bind the request payload using `ctx.Bind(&<SERVICE_REQUEST>)`.
- Process the request and generate a response.

## Registering the gRPC Service with Gofr
Expand All @@ -138,7 +138,7 @@ import (
func main() {
app := gofr.New()

packageName.Register{serviceName}ServerWithGofr(app, &{packageName}.New{serviceName}GoFrServer())
packageName.Register<SERVICE_NAME>ServerWithGofr(app, &<PACKAGE_NAME>.New<SERVICE_NAME>GoFrServer())

app.Run()
}
Expand All @@ -163,7 +163,7 @@ func main() {
grpc.ConnectionTimeout(10 * time.Second),
)

packageName.Register{serviceName}ServerWithGofr(app, &{packageName}.New{serviceName}GoFrServer())
packageName.Register<SERVICE_NAME>ServerWithGofr(app, &<PACKAGE_NAME>.New<SERVICE_NAME>GoFrServer())

app.Run()
}
Expand All @@ -180,7 +180,7 @@ func main() {

app.AddGRPCUnaryInterceptors(authInterceptor)

packageName.Register{serviceName}ServerWithGofr(app, &{packageName}.New{serviceName}GoFrServer())
packageName.Register<SERVICE_NAME>ServerWithGofr(app, &<PACKAGE_NAME>.New<SERVICE_NAME>GoFrServer())

app.Run()
}
Expand Down Expand Up @@ -227,26 +227,26 @@ For more details on adding additional interceptors and server options, refer to
```bash
gofr wrap grpc client -proto=./path/your/proto/file
```
This command leverages the `gofr-cli` to generate a `{serviceName}_client.go` file (e.g., `customer_client.go`). This file must not be modified.
This command leverages the `gofr-cli` to generate a `<SERVICE_NAME>_client.go` file (e.g., `customer_client.go`). This file must not be modified.

**2. Register the connection to your gRPC service inside your {serviceMethod} and make inter-service calls as follows :**
**2. Register the connection to your gRPC service inside your <SERVICE_METHOD> and make inter-service calls as follows :**

```go
// gRPC Handler with context support
func {serviceMethod}(ctx *gofr.Context) (*{serviceResponse}, error) {
func <SERVICE_METHOD>(ctx *gofr.Context) (*<SERVICE_RESPONSE>, error) {
// Create the gRPC client
srv, err := New{serviceName}GoFrClient("your-grpc-server-host", ctx.Metrics())
srv, err := New<SERVICE_NAME>GoFrClient("your-grpc-server-host", ctx.Metrics())
if err != nil {
return nil, err
}

// Prepare the request
req := &{serviceRequest}{
req := &<SERVICE_REQUEST>{
// populate fields as necessary
}

// Call the gRPC method with tracing/metrics enabled
res, err := srv.{serviceMethod}(ctx, req)
res, err := srv.<SERVICE_METHOD>(ctx, req)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -307,7 +307,7 @@ func main() {
app := gofr.New()

// Create a gRPC client for the service
gRPCClient, err := client.New{serviceName}GoFrClient(
gRPCClient, err := client.New<SERVICE_NAME>GoFrClient(
app.Config.Get("GRPC_SERVER_HOST"),
app.Metrics(),
grpc.WithChainUnaryInterceptor(MetadataUnaryInterceptor),
Expand Down Expand Up @@ -374,7 +374,7 @@ func main() {
return
}

gRPCClient, err := client.New{serviceName}GoFrClient(
gRPCClient, err := client.New<SERVICE_NAME>GoFrClient(
app.Config.Get("GRPC_SERVER_HOST"),
app.Metrics(),
grpc.WithTransportCredentials(creds),
Expand Down Expand Up @@ -409,7 +409,7 @@ GoFr provides built-in health checks for gRPC services, enabling observability,
### Client Interface

```go
type {serviceName}GoFrClient interface {
type <SERVICE_NAME>GoFrClient interface {
SayHello(*gofr.Context, *HelloRequest, ...grpc.CallOption) (*HelloResponse, error)
health
}
Expand All @@ -422,7 +422,7 @@ type health interface {

### Server Integration
```go
type {serviceName}GoFrServer struct {
type <SERVICE_NAME>GoFrServer struct {
health *healthServer
}
```
Expand Down
21 changes: 21 additions & 0 deletions docs/advanced-guide/http-communication/page.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,24 @@ GoFr provides its user with additional configurational options while registering
- **DefaultHeaders** - This option allows user to set some default headers that will be propagated to the downstream HTTP Service every time it is being called.
- **HealthConfig** - This option allows user to add the `HealthEndpoint` along with `Timeout` to enable and perform the timely health checks for downstream HTTP Service.
- **RetryConfig** - This option allows user to add the maximum number of retry count if before returning error if any downstream HTTP Service fails.
- **RateLimiterConfig** - This option allows user to configure rate limiting for downstream service calls using token bucket algorithm. It controls the request rate to prevent overwhelming dependent services and supports both in-memory and Redis-based implementations.

**Rate Limiter Store: Customization**
GoFr allows you to use a custom rate limiter store by implementing the RateLimiterStore interface.This enables integration with any backend (e.g., Redis, database, or custom logic)
Interface:
```go
type RateLimiterStore interface {
Allow(ctx context.Context, key string, config RateLimiterConfig) (allowed bool, retryAfter time.Duration, err error)
StartCleanup(ctx context.Context)
StopCleanup()
}
```

#### Usage:

```go
rc := redis.NewClient(a.Config, a.Logger(), a.Metrics())

a.AddHTTPService("cat-facts", "https://catfact.ninja",
service.NewAPIKeyConfig("some-random-key"),
service.NewBasicAuthConfig("username", "password"),
Expand All @@ -119,5 +133,12 @@ a.AddHTTPService("cat-facts", "https://catfact.ninja",
&service.RetryConfig{
MaxRetries: 5
},

&service.RateLimiterConfig{
Requests: 5,
Window: time.Minute,
Burst: 10,
Store: service.NewRedisRateLimiterStore(rc)}, // Skip this field to use in-memory store
},
)
```
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/google/uuid v1.6.0
github.com/gorilla/mux v1.8.1
github.com/gorilla/websocket v1.5.3
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0
github.com/grpc-ecosystem/go-grpc-middleware/v2 v2.3.2
github.com/joho/godotenv v1.5.1
github.com/lib/pq v1.10.9
github.com/pkg/errors v0.9.1
Expand Down
Loading
Loading