Skip to content

Commit c72bc69

Browse files
committed
Merge branch 'main' of github.com:gofr-dev/gofr
2 parents ab76d66 + 8ea784b commit c72bc69

File tree

37 files changed

+1273
-188
lines changed

37 files changed

+1273
-188
lines changed

.github/workflows/go.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,6 @@ jobs:
374374

375375
# Check file naming conventions using ls-lint
376376
- name: Check for file names errors
377-
uses: ls-lint/action@v2.2.3
377+
uses: ls-lint/action@v2.3.0
378378
with:
379379
config: .ls-lint.yml

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,4 @@ If your PR is merged, or if you contribute by writing articles or promoting GoFr
137137

138138
### Partners
139139

140-
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.png" alt="JetBrains logo" width="200">
140+
<img src="https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.png" alt="JetBrains logo" width="200">

docs/advanced-guide/grpc/page.md

Lines changed: 180 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ syntax = "proto3";
5656
option go_package = "path/to/your/proto/file";
5757
5858
service {serviceName}Service {
59-
rpc {serviceMethod} ({serviceRequest}) returns ({serviceResponse}) {}
59+
rpc {serviceMethod} ({serviceRequest}) returns ({serviceResponse}) {}
6060
}
6161
```
6262

@@ -67,16 +67,16 @@ procedure call. Below is a generic representation for services' gRPC messages ty
6767

6868
```protobuf
6969
message {serviceRequest} {
70-
int64 id = 1;
71-
string name = 2;
72-
// other fields that can be passed
70+
int64 id = 1;
71+
string name = 2;
72+
// other fields that can be passed
7373
}
7474
7575
message {serviceResponse} {
76-
int64 id = 1;
77-
string name = 2;
78-
string address = 3;
79-
// other customer related fields
76+
int64 id = 1;
77+
string name = 2;
78+
string address = 3;
79+
// other customer related fields
8080
}
8181
```
8282

@@ -146,6 +146,56 @@ func main() {
146146

147147
>Note: By default, gRPC server will run on port 9000, to customize the port users can set `GRPC_PORT` config in the .env
148148
149+
## Adding gRPC Server Options
150+
151+
To customize your gRPC server, use `AddGRPCServerOptions()`.
152+
153+
### Example: Enabling TLS & other ServerOptions
154+
```go
155+
func main() {
156+
app := gofr.New()
157+
158+
// Add TLS credentials and connection timeout in one call
159+
creds, _ := credentials.NewServerTLSFromFile("server-cert.pem", "server-key.pem")
160+
161+
app.AddGRPCServerOptions(
162+
grpc.Creds(creds),
163+
grpc.ConnectionTimeout(10 * time.Second),
164+
)
165+
166+
packageName.Register{serviceName}ServerWithGofr(app, &{packageName}.New{serviceName}GoFrServer())
167+
168+
app.Run()
169+
}
170+
```
171+
172+
## Adding Custom Unary Interceptors
173+
174+
Interceptors help in implementing authentication, validation, request transformation, and error handling.
175+
176+
### Example: Authentication Interceptor
177+
```go
178+
func main() {
179+
app := gofr.New()
180+
181+
app.AddGRPCUnaryInterceptors(authInterceptor)
182+
183+
packageName.Register{serviceName}ServerWithGofr(app, &{packageName}.New{serviceName}GoFrServer())
184+
185+
app.Run()
186+
}
187+
188+
func authInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (any, error) {
189+
if !isAuthenticated(ctx) {
190+
return nil, status.Errorf(codes.Unauthenticated, "authentication failed")
191+
}
192+
193+
return handler(ctx, req)
194+
}
195+
```
196+
197+
For more details on adding additional interceptors and server options, refer to the [official gRPC Go package](https://pkg.go.dev/google.golang.org/grpc#ServerOption).
198+
149199
## Generating gRPC Client using `gofr wrap grpc client`
150200

151201
**1. Use the `gofr wrap grpc client` Command:**
@@ -159,27 +209,132 @@ This command leverages the `gofr-cli` to generate a `{serviceName}_client.go` fi
159209
```go
160210
// gRPC Handler with context support
161211
func {serviceMethod}(ctx *gofr.Context) (*{serviceResponse}, error) {
162-
// Create the gRPC client
163-
srv, err := New{serviceName}GoFrClient("your-grpc-server-host", ctx.Metrics())
164-
if err != nil {
165-
return nil, err
212+
// Create the gRPC client
213+
srv, err := New{serviceName}GoFrClient("your-grpc-server-host", ctx.Metrics())
214+
if err != nil {
215+
return nil, err
216+
}
217+
218+
// Prepare the request
219+
req := &{serviceRequest}{
220+
// populate fields as necessary
221+
}
222+
223+
// Call the gRPC method with tracing/metrics enabled
224+
res, err := srv.{serviceMethod}(ctx, req)
225+
if err != nil {
226+
return nil, err
227+
}
228+
229+
return res, nil
166230
}
231+
```
167232

168-
// Prepare the request
169-
req := &{serviceRequest}{
170-
// populate fields as necessary
233+
234+
## Customizing gRPC Client with DialOptions
235+
236+
GoFr provides flexibility to customize your gRPC client connections using gRPC `DialOptions`. This allows users to configure aspects such as transport security, interceptors, and load balancing policies.
237+
You can pass optional parameters while creating your gRPC client to tailor the connection to your needs. Here’s an example of a Unary Interceptor that sets metadata on outgoing requests:
238+
239+
```go
240+
func main() {
241+
app := gofr.New()
242+
243+
// Create a gRPC client for the service
244+
gRPCClient, err := client.New{serviceName}GoFrClient(
245+
app.Config.Get("GRPC_SERVER_HOST"),
246+
app.Metrics(),
247+
grpc.WithChainUnaryInterceptor(MetadataUnaryInterceptor),
248+
)
249+
250+
if err != nil {
251+
app.Logger().Errorf("Failed to create gRPC client: %v", err)
252+
return
253+
}
254+
255+
greet := NewGreetHandler(gRPCClient)
256+
257+
app.GET("/hello", greet.Hello)
258+
259+
app.Run()
171260
}
172261

173-
// Call the gRPC method with tracing/metrics enabled
174-
res, err := srv.{serviceMethod}(ctx, req)
175-
if err != nil {
176-
return nil, err
262+
// MetadataUnaryInterceptor sets a custom metadata value on outgoing requests
263+
func MetadataUnaryInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
264+
md := metadata.Pairs("client-id", "GoFr-Client-123")
265+
ctx = metadata.NewOutgoingContext(ctx, md)
266+
267+
err := invoker(ctx, method, req, reply, cc, opts...)
268+
if err != nil {
269+
return fmt.Errorf("Error in %s: %v", method, err)
270+
}
271+
272+
return err
177273
}
274+
```
275+
276+
This interceptor sets a metadata key `client-id` with a value of `GoFr-Client-123` for each request. Metadata can be used for authentication, tracing, or custom behaviors.
277+
278+
### Using TLS Credentials and Advanced Service Config
279+
By default, gRPC connections in GoFr are made over insecure connections, which is not recommended for production. You can override this behavior using TLS credentials. Additionally, a more comprehensive service configuration can define retry policies and other settings:
280+
281+
```go
282+
import (
283+
"google.golang.org/grpc"
284+
"google.golang.org/grpc/credentials"
285+
)
286+
287+
// The default serviceConfig in GoFr only sets the loadBalancingPolicy to "round_robin".
288+
const serviceConfig = `{
289+
"loadBalancingPolicy": "round_robin",
290+
"methodConfig": [{
291+
"name": [{"service": "HelloService"}],
292+
"retryPolicy": {
293+
"maxAttempts": 4,
294+
"initialBackoff": "0.1s",
295+
"maxBackoff": "1s",
296+
"backoffMultiplier": 2.0,
297+
"retryableStatusCodes": ["UNAVAILABLE", "RESOURCE_EXHAUSTED"]
298+
}
299+
}]
300+
}`
301+
302+
func main() {
303+
app := gofr.New()
178304

179-
return res, nil
305+
creds, err := credentials.NewClientTLSFromFile("path/to/cert.pem", "")
306+
if err != nil {
307+
app.Logger().Errorf("Failed to load TLS certificate: %v", err)
308+
return
309+
}
310+
311+
gRPCClient, err := client.New{serviceName}GoFrClient(
312+
app.Config.Get("GRPC_SERVER_HOST"),
313+
app.Metrics(),
314+
grpc.WithTransportCredentials(creds),
315+
grpc.WithDefaultServiceConfig(serviceConfig),
316+
)
317+
318+
if err != nil {
319+
app.Logger().Errorf("Failed to create gRPC client: %v", err)
320+
return
321+
}
322+
323+
greet := NewGreetHandler(gRPCClient)
324+
325+
app.GET("/hello", greet.Hello)
326+
327+
app.Run()
180328
}
181329
```
182330

331+
In this example:
332+
- `WithTransportCredentials` sets up TLS security.
333+
- `WithDefaultServiceConfig` defines retry policies with exponential backoff and specific retryable status codes.
334+
335+
### Further Reading
336+
For more details on configurable DialOptions, refer to the [official gRPC package for Go](https://pkg.go.dev/google.golang.org/grpc#DialOption).
337+
183338
## HealthChecks in GoFr's gRPC Service/Clients
184339
Health Checks in GoFr's gRPC Services
185340

@@ -189,20 +344,20 @@ GoFr provides built-in health checks for gRPC services, enabling observability,
189344

190345
```go
191346
type {serviceName}GoFrClient interface {
192-
SayHello(*gofr.Context, *HelloRequest, ...grpc.CallOption) (*HelloResponse, error)
193-
health
347+
SayHello(*gofr.Context, *HelloRequest, ...grpc.CallOption) (*HelloResponse, error)
348+
health
194349
}
195350

196351
type health interface {
197-
Check(ctx *gofr.Context, in *grpc_health_v1.HealthCheckRequest, opts ...grpc.CallOption) (*grpc_health_v1.HealthCheckResponse, error)
198-
Watch(ctx *gofr.Context, in *grpc_health_v1.HealthCheckRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[grpc_health_v1.HealthCheckResponse], error)
352+
Check(ctx *gofr.Context, in *grpc_health_v1.HealthCheckRequest, opts ...grpc.CallOption) (*grpc_health_v1.HealthCheckResponse, error)
353+
Watch(ctx *gofr.Context, in *grpc_health_v1.HealthCheckRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[grpc_health_v1.HealthCheckResponse], error)
199354
}
200355
```
201356

202357
### Server Integration
203358
```go
204359
type {serviceName}GoFrServer struct {
205-
health *healthServer
360+
health *healthServer
206361
}
207362
```
208363
Supported Methods for HealthCheck :

docs/datasources/getting-started/page.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ as unnecessary database drivers are not being compiled and added to the build.
9393
-
9494
-
9595
-
96-
-
96+
-
9797

9898
---
9999

docs/public/metrics-dashboard.png

514 KB
Loading
37.5 KB
Binary file not shown.
39 KB
Binary file not shown.
92.2 KB
Binary file not shown.
45 KB
Binary file not shown.
59.4 KB
Binary file not shown.
60.5 KB
Binary file not shown.

docs/public/reviewers/vignesh.webp

28.1 KB
Binary file not shown.
23.1 KB
Binary file not shown.

docs/quick-start/connecting-mysql/page.md

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,12 @@ Just like Redis GoFr also supports connection to SQL (MySQL, MariaDB, and Postgr
44

55
## Setup
66

7-
Users can run MySQL and create a database locally using the following Docker command:
7+
Users can run MySQL/MariaDB and create a database locally using the following Docker command:
88

99
```bash
10-
docker run --name gofr-mysql -e MYSQL_ROOT_PASSWORD=root123 -e MYSQL_DATABASE=test_db -p 3306:3306 -d mysql:8.0.30
10+
docker run --name gofr-db -e MYSQL_ROOT_PASSWORD=root123 -e MYSQL_DATABASE=test_db -p 3306:3306 -d mysql:8.0.30
1111
```
1212

13-
For MariaDB, you would run:
14-
15-
```bash
16-
docker run --name gofr-mariadb -e MYSQL_ROOT_PASSWORD=root123 -e MYSQL_DATABASE=test_db -p 3306:3306 -d mariadb:latest
17-
```
18-
19-
2013
Access `test_db` database and create table customer with columns `id` and `name`. Change mysql to mariadb as needed:
2114

2215
```bash
@@ -43,11 +36,7 @@ DB_PASSWORD=root123
4336
DB_NAME=test_db
4437
DB_PORT=3306
4538
DB_DIALECT=mysql
46-
DB_CHARSET=
47-
48-
# DB_CHARSET: The character set for database connection (default: utf8).
49-
# The `DB_CHARSET` defaults to utf8, but setting it to utf8mb4 is recommended if you need full Unicode support,
50-
# including emojis and special characters.
39+
DB_CHARSET=utf8 #(optional)
5140
```
5241

5342
Now in the following example, we'll store customer data using **POST** `/customer` and then use **GET** `/customer` to retrieve the same.

docs/quick-start/connecting-redis/page.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,7 @@ GoFr simplifies the process of connecting to Redis.
66

77
Ensure we have Redis installed on our system.
88

9-
Optionally, We can use Docker to set up a development environment as described below.
10-
11-
```bash
12-
docker run --name gofr-redis -p 6379:6379 -d redis
13-
```
14-
15-
We can also set up a development environment with password authentication as described below.
9+
Optionally, We can use Docker to set up a development environment with password authentication as described below.
1610

1711
```bash
1812
docker run --name gofr-redis -p 2002:6379 -d \

docs/quick-start/observability/page.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,17 @@ For example: When running application locally, we can access /metrics endpoint o
137137

138138
GoFr also supports creating {% new-tab-link newtab=false title="custom metrics" href="/docs/advanced-guide/publishing-custom-metrics" /%}.
139139

140+
### Example Dashboard
141+
142+
These metrics can be easily consumed by monitoring systems like {% new-tab-link title="Prometheus" href="https://prometheus.io/" /%}
143+
and visualized in dashboards using tools like {% new-tab-link title="Grafana" href="https://grafana.com/" /%}.
144+
145+
Here's a sample Grafana dashboard utilizing GoFr's metrics:
146+
147+
{% figure src="/metrics-dashboard.png" alt="Grafana Dashboard showing GoFr metrics including HTTP request rates,
148+
response times etc." caption="Example monitoring dashboard using GoFr's built-in metrics" /%}
149+
150+
140151
## Tracing
141152

142153
{% new-tab-link title="Tracing" href="https://opentelemetry.io/docs/concepts/signals/#traces" /%} is a powerful tool for gaining insights into your application's behavior, identifying bottlenecks, and improving

docs/references/configs/page.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,12 @@ This document lists all the configuration options supported by the GoFr framewor
193193
- Currently supported only for PostgreSQL, with Default certificate file.
194194
- disable
195195

196+
---
197+
198+
- DB_CHARSET
199+
- The character set for database connection
200+
- utf8
201+
196202
{% /table %}
197203

198204
### Redis

0 commit comments

Comments
 (0)