Skip to content

Releases: gofr-dev/gofr

v1.42.0

20 Jun 04:50
276922e
Compare
Choose a tag to compare

v1.42.0

🚀 Features

1. CockroachDB Support

GoFr now supports CockroachDB, a distributed cloud-native SQL database.
Developers can now configure GoFr services to connect to CockroachDB using simple environment variables.

🔧 Configuration:

DB_DIALECT=cockroachdb
DB_HOST=localhost
DB_PORT=26257
DB_USER=root
DB_PASSWORD=your-password
DB_NAME=defaultdb
DB_SSL_MODE=require

For more details, refer to the SQL usage guide.

🛠️ Improvements

1. gRPC Reflection Toggle via Config

GoFr now supports enabling/disabling gRPC server reflection using a simple config flag:

GRPC_ENABLE_REFLECTION=true

🔍 When to enable:

  • Development & Debugging: Use with tools like grpcurl, Postman, or Evans.

  • Internal Networks: Safe in private, trusted environments.

  • CI/CD Pipelines: Ideal for service discovery in automated setups.

This allows dynamic inspection of gRPC services while maintaining control over exposure.

🛠️ Fixes

1. Supabase Healthcheck Issue Resolved

Resolved an issue where Supabase-backed services were not responding properly to health checks due to incorrect handling of internal pings.

2. Fixed Data Race in Metrics Gauges

Addressed a concurrency bug where the internal float64Gauge map was accessed without synchronization. Proper locking is now in place around map access to avoid data races during concurrent SetGauge and metric reads.

3. App Name & Version Initialization Bug

Fixed a configuration issue where AppName and AppVersion were incorrectly defaulting to gofr-app and dev, even when explicitly provided by the user. These values now correctly reflect user-specified configuration during startup.

v1.41.0

12 Jun 18:05
9e5d5bb
Compare
Choose a tag to compare

v1.41.0

🔧 Improvements

1. New HTTP Error Type: ErrorRecordNotFound

A new standardized error type http.ErrorRecordNotFound has been introduced to gracefully handle scenarios where no records are found in the database.

Example:

return  nil, http.ErrorRecordNotFound{
    Message: "User not found with the given ID",
}

This improves semantic clarity and enables better client-side handling for empty-query results.

2. Improved Cron Job Observability

All cron jobs in GoFr now come with built-in logger and tracing support.

  • Logs from scheduled tasks are now clearly visible.

  • Each recurring job run is automatically tagged with a unique trace ID, making it easier to trace, debug, and monitor scheduled executions across your system.

This ensures better observability for background tasks without requiring additional instrumentation.

🐛 Fixes

1. Supabase Connection Issue Resolved

Previously, Supabase connections were not initializing correctly in GoFr due to a missing dialect registration. Supabase-backed services will now connect without issues—no manual fixes required.

v1.40.1

06 Jun 06:26
9e5d5bb
Compare
Choose a tag to compare

v1.40.1

🔧 Dependency Updates

Upgraded all externalized datasource dependencies to their latest stable versions for improved performance, security, and compatibility across supported services.

v1.40.0

23 May 12:07
493ab96
Compare
Choose a tag to compare

v1.40.0

🚀 Features

Support for Supabase Database

Users can now connect their GoFr services to a Supabase database using environment variables. This feature supports both direct and pooled connections, enabling secure and scalable Postgres usage via Supabase.

🔧 Environment Variable Setup:

DB_DIALECT=supabase
DB_HOST=db.[PROJECT_REF].supabase.co  # Optional, derived from PROJECT_REF
DB_USER=postgres                      # Or database user name
DB_PASSWORD=password
DB_NAME=postgres                      # Or your database name
DB_PORT=5432                          # Optional, defaults based on connection type
DB_SSL_MODE=require                   # Optional, forced to "require" for Supabase

# Supabase-specific configs
SUPABASE_PROJECT_REF=your_project_ref
SUPABASE_CONNECTION_TYPE=direct       # Options: direct, session, transaction
SUPABASE_REGION=us-east-1             # Required for pooled connections

# Alternatively, can provide full connection string
DATABASE_URL=postgresql://postgres:password@db.your_project_ref.supabase.co:5432/postgres

Inter-Service WebSocket Communication

GoFr now supports Inter-Service WebSocket Communication, enabling services to exchange real-time messages over WebSocket connections. Ideal for microservices needing live updates or event-driven communication.

🔑 Key Methods:

  • AddWSService: Register a persistent WebSocket connection to another service with optional auto-reconnect.

  • WriteMessageToService: Send messages to any registered service.

✅ Example Usage:

func main(){

	app := gofr.New()

	err := app.AddWSService("notification-service", "ws://notifications.example.com/ws", nil, true, 5*time.Second) 
	if err != nil {
	    app.Logger.Errorf("Failed to add WebSocket service: %v", err) 
	    return 
	}

	app.POST("/send-notification", func(ctx *gofr.Context) (any, error) {
	    message := map[string]string{ 
		    "title": "New Message", 
		    "content": 	"You have a new notification!",
	    }

	    err := ctx.WriteMessageToService("notification-service", message)
	    if err != nil { 
		    return  nil, err
	    } 
	    
		return  "Notification sent successfully!", nil 
		})

	app.Run()
}

This enables resilient, real-time service communication with minimal configuration.

🔧 Improvements

1. New HTTP Error Type: ServiceUnavailable

A new standardized error type ErrorServiceUnavailable has been introduced for representing service unavailability due to dependency issues like database failures or third-party service outages.

⚙️ Use Case Example:

err := http.ErrorServiceUnavailable{
    Dependency: "PostgreSQL",
    ErrorMessage: "Connection timeout",
}

This improvement enhances observability and clarity when dealing with critical external failures.

v1.39.1

15 May 12:56
aa6e3e6
Compare
Choose a tag to compare

v1.39.1

🛠 Improvements

  1. Disable Logs for Health & Alive Probes

    Logging for health check routes (/.well-known/health and /.well-known/alive) can now be disabled to reduce log clutter in environments with frequent probe calls (e.g., Kubernetes).

    Set the following environment variable:

    LOG_DISABLE_PROBES=true
  2. TraceID Now Included in Context-Based Logging

    Logs emitted using ctx.Logger() now automatically include the request traceID. This enhances traceability across services and allows easier debugging in distributed systems.

    Example log before:

    {"message": "User created", "level": "INFO"}

    After:

    {"message": "User created", "trace_id": "3ac9f5e7c12e...", "level": "INFO"}

    No additional configuration needed—this is now built-in.

  3. Enhanced ArangoDB Query Options Support

    You can now pass advanced query and subquery options when executing AQL queries via GoFr’s ArangoDB client.

    options := map[string]any{
        "count":     true,
        "batchSize": 100,
        "options": map[string]any{
            "fullCount": true,
            "profile":   2,
        },
    }

    Supported keys include (but are not limited to):

    • QueryOptions:

      • count, batchSize, ttl, cache, memoryLimit
    • QuerySubOptions (under options key):

      • fullCount, allowRetry, stream, optimizer, profile, maxRuntime, skipInaccessibleCollections, and more

    Example usage:

    err := ctx.ArangoDB.Query(ctx, "myDatabase", query, bindVars, &results, options)

    This update gives you full control over AQL query execution for performance tuning, streaming, profiling, and more.

v1.39.0

08 May 16:19
c3c443a
Compare
Choose a tag to compare

v1.39.0

🚀 Features

gRPC Streaming Support

GoFr now supports all gRPC streaming types, unlocking full duplex communication capabilities:

  • Server-side streaming
  • Client-side streaming c
  • Bidirectional streaming
    Auto-generated handlers for streaming methods with built-in metrics and tracing support for all streaming calls

Note: Requires gofr-cli v0.7.0 or higher.
Refer to the examples to explore usage patterns.

Redirect Support in HTTP Handlers

Handlers can now trigger client redirects by returning a response.Redirect object:

import (
    "gofr.dev/pkg/gofr"
    "gofr.dev/pkg/gofr/http/response"
)

func main() {
    app := gofr.New()

    app.GET("/old-page", func(ctx *gofr.Context) (any, error) {
        return response.Redirect{URL: "https://example.com/new-page"}, nil
    })

    app.Run()
}

Use this for SEO-friendly permanent or temporary redirects from legacy URLs.

🛠 Improvements

1. TLS Support for Redis

Redis connections in GoFr can now be secured using TLS. This enhancement enables secure communication in production and enterprise deployments. Configuration is done via environment variables:

Environment Variable Description
REDIS_TLS_ENABLED Set to "true" to enable TLS support
REDIS_TLS_CA_CERT_PATH File path to the CA certificate to verify Redis server identity
REDIS_TLS_CERT_PATH File path to the client certificate (for mTLS connections)
REDIS_TLS_KEY_PATH File path to the client private key (for mTLS connections)

v1.38.0

24 Apr 15:41
72e836f
Compare
Choose a tag to compare

Release - v1.38.0

🚀 Features

Elasticsearch Integration Support

  • GoFr now supports Elasticsearch as a pluggable data source with a standard interface for document indexing, searching, and cluster management.

  • Developers can inject any compatible Elasticsearch client that implements the following interface:

    type Elasticsearch interface {
        Connect()
        CreateIndex(ctx context.Context, index string, settings map[string]any) error 
        DeleteIndex(ctx context.Context, index string) error 
        IndexDocument(ctx context.Context, index, id string, document any) error 
        GetDocument(ctx context.Context, index, id string) (map[string]any, error)
        UpdateDocument(ctx context.Context, index, id string, update map[string]any) error 
        DeleteDocument(ctx context.Context, index, id string) error 
        Search(ctx context.Context, indices []string, query map[string]any) (map[string]any, error)
        Bulk(ctx context.Context, operations []map[string]any) (map[string]any, error)
        HealthChecker
    }
  • Official GoFr-compatible driver is available via:

    go get gofr.dev/pkg/gofr/datasource/elasticsearch@latest
    
  • Example usage in your main.go:

    func main (){
    	    app := gofr.New()
    	    
    		es := elasticsearch.New(elasticsearch.Config{
    	        Addresses: []string{"http://localhost:9200"},
    	        Username: "elastic",
    	        Password: "changeme",
    	    })
    
    	    app.AddElasticsearch(es)
    	    
    		app.Run ()
    }
  • Checkout our official documentation for more details.

v1.37.1

16 Apr 04:13
d969729
Compare
Choose a tag to compare

Release - v1.37.1

🚀 Improvements

Extended Error Responses (RFC 9457-style)

  • GoFr now supports extended error responses following the RFC 9457 specification.

  • Developers can implement the new ResponseMarshaler interface to enrich error responses with custom fields beyond the standard error message and status code.

    type ResponseMarshaler interface {
        Response() map[string]any
    }
  • Example:

     type ValidationError struct {
         Field string 
         Message string 
         Code int 
     } 
    
     func  (e ValidationError) Error() string { 
     	return e.Message 
     } 
    
     func  (e ValidationError) StatusCode() int { 
     	return e.Code 
     } 
    
     func  (e ValidationError) Response() map[string]any { 
     	return  map[string]any{ 
     		"field":   e.Field, 
     		"type": "validation_error", 
     		"details": "Invalid input format",
         }
     }

    ⚠️ Note: The message field is automatically populated from the Error() method. Custom fields with the name "message" in the Response() map should not be used as they will be ignored in favor of the Error() value.

    This feature allows more descriptive and structured error responses, ideal for client-side validation, API debugging, and frontend integration.

🛠 Fixes

1. WebSocket: Fixed Concurrent Write Panic

  • WebSocket writes are now thread-safe. Previously, concurrent calls to WriteMessageToSocket() caused race conditions and panics. Writes are now internally synchronized.

2. NATS: Synchronous Connection Setup

  • NATS connections are now established synchronously to prevent errJetStreamNotConfigured errors when calling jetStream() immediately after Connect().

v1.37.0

08 Apr 14:29
c72bc69
Compare
Choose a tag to compare

🚀 Features

1. Dgraph Migration Support

  • Added native migration capabilities for Dgraph through new methods, enabling precise schema evolution:
    // Apply or update the complete Dgraph schema 
    ApplySchema(ctx context.Context, schema string) error
    // Atomically create or update a field definition
    AddOrUpdateField(ctx context.Context, fieldName, fieldType, directives string) error  
    // Permanently remove a field/predicate and its associated data 
    DropField(ctx context.Context, fieldName string) error	 
  • Refer to the official documentation for full usage details.

🛠 Improvements

1. gRPC Server Configuration via AddGRPCServerOptions

  • GoFr now allows configuring advanced gRPC ServerOptions.

  • Example: Enabling TLS and setting a connection timeout

    creds, _ := credentials.NewServerTLSFromFile("server-cert.pem", "server-key.pem")
    
    app.AddGRPCServerOptions(
        grpc.Creds(creds),
        grpc.ConnectionTimeout(10*time.Second),
    )
  • Refer to the official documentation to know more.

2. Add Custom Unary Interceptors

app.AddGRPCUnaryInterceptors(authInterceptor)
  • GoFr already logs, traces and sends default metrics for all gRPC calls. No external interceptor for such features is necessary. Custom server-side UnaryServerInterceptors can now be registered easily for use cases like:

    • Authentication
    • Request validation
  • For guidance on how to define Server UnaryInterceptors that can be added in your GoFr's gRPC server, check out the official documentation.

3. Advanced gRPC Client DialOptions Support

  • Clients can now be customized extensively via grpc.DialOptions.
    This allows to add gRPC services with :
    - Secure TLS communication
    - Load-balanced connections
    - Retry logic
    - Context-aware metadata injection (useful for tracing and auth)

    const serviceConfig = `{
      "loadBalancingPolicy": "round_robin",
      "methodConfig": [{
        "name": [{"service": "HelloService"}],
        "retryPolicy": {
          "maxAttempts": 4,
          "initialBackoff": "0.1s",
          "maxBackoff": "1s",
          "backoffMultiplier": 2.0,
          "retryableStatusCodes": ["UNAVAILABLE", "RESOURCE_EXHAUSTED"]
        }
      }]
    }` 
    
    // Metadata interceptor to add client ID to each request
    func  MetadataUnaryInterceptor(ctx context.Context, method string, req, reply any,
        cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption,
    ) error {
        md := metadata.Pairs("client-id", "f1b1a372-02f5-4065-9ccf-113d34a3d5ed")
        
        ctx = metadata.NewOutgoingContext(ctx, md) 
    
        return invoker(ctx, method, req, reply, cc, opts...)
    } 
    
    func  main() {
        app := gofr.New()
    
        creds, err := credentials.NewClientTLSFromFile("cert.pem", "") if err != nil {
            app.Logger().Errorf("TLS error: %v", err) return }
    
        grpcClient, err := client.NewHelloServiceGoFrClient(
            app.Config.Get("GRPC_SERVER_HOST"),
            app.Metrics(),
            grpc.WithTransportCredentials(creds),
            grpc.WithDefaultServiceConfig(serviceConfig),
            grpc.WithChainUnaryInterceptor(MetadataUnaryInterceptor),
        ) 
    
    	if err != nil {
            app.Logger().Errorf("Failed to create client: %v", err) return 
        }
    
        handler := NewGreetHandler(grpcClient)
        
        app.GET("/hello", handler.Hello)
        
        app.Run()
    }

🛠 Fixes

1. SurrealDB Update Method: Unexpected Behavior Fixed

  • Regardless of the input, the Update method previously inserted an unexpected hardcoded key-value pair. The method now correctly updates only the intended fields as passed by the caller.

v1.36.0

25 Mar 15:02
ab76d66
Compare
Choose a tag to compare

Release - v1.36.0

🚀 Features

1. SurrealDB Migration Support

  • Added support for database migration operations in SurrealDB.
  • Supported methods include:
     // Creates a new namespace in SurrealDB.
     CreateNamespace(ctx context.Context, namespace string) error  
     // Creates a new database in SurrealDB.
     CreateDatabase(ctx context.Context, database string) error 
     // Deletes a namespace from SurrealDB.
     DropNamespace(ctx context.Context, namespace string) error
     // Deletes a database from SurrealDB.  
     DropDatabase(ctx context.Context, database string) error  
  • Refer to our official documentation to know more.

🛠 Improvements

1. Default Metrics for SurrealDB Data Source

  • Introduced default metric collection for SurrealDB at the specified METRICS_PORT, enabling better observability and performance monitoring.

2. JWT Claim Validations

  • EnableOAuth now takes an additional JWT validation options as jwt.ParserOption, allowing fine-grained control over claim validation.
  • Example :
     app.EnableOAuth(
     	"http://jwks-endpoint",
     	20,
     	jwt.WithExpirationRequired(), // to enforce presence of exp claim in every token
     	jwt.WithAudience("https://api.example.com"),
     	jwt.WithIssuer("https://auth.example.com")
     )
  • To know more about the different claim validation options, check out our official documentation.

🛠 Fixes

1. pprof Profiling Enhancements

  • Previously, the pprof endpoint was restricted to being enabled only when the APP_ENV=DEBUG environment variable was set, and it ran on the specified HTTP_PORT. This prevented users from loading their different environments, for e.g. stage or production configurations if we set APP_ENV as DEBUG for profiling.
  • GoFr now automatically enables pprof profiling on METRICS_PORT (default: 2121).
  • Profiling endpoints include :
    • /debug/pprof/cmdline
    • /debug/pprof/profile
    • /debug/pprof/symbol
    • /debug/pprof/trace
    • /debug/pprof/ (index)

For more information on setting up and using profiling in your application, refer to our official documentation.