vulpes

module
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 8, 2026 License: Apache-2.0

README

Vulpes: A Go Microservice Toolkit

vulpes (Latin for fox) is a collection of cohesive, opinionated Go packages designed to accelerate the development of robust, production-ready, and maintainable microservices. It provides a solid foundation by handling common backend concerns, allowing developers to focus on business logic.

Built with a focus on gRPC and modern best practices, Vulpes offers sensible defaults and a clean, decoupled architecture.

Core Philosophy

  • Productivity: Get from idea to a running service quickly. Boilerplate for database connections, logging, gRPC servers, and more is handled for you.
  • Best Practices Built-in: Encourages patterns like structured logging, dependency injection, and self-describing data models.
  • Decoupled and Extensible: Each package is designed to be useful on its own, but they shine when used together. The architecture is modular and easy to extend.
  • Opinionated, Not Restrictive: Provides strong defaults and patterns but allows for customization where it matters.

Key Features

  • Rapid gRPC & RESTful API Development: Easily set up a gRPC server that also serves a JSON RESTful gateway on the same port.
  • Type-Safe & Self-Describing Database Models: An abstraction layer for MongoDB that encourages models to define their own schema and indexes.
  • High-Performance Structured Logging: A simple, global logger built on Zap that provides environment-aware, structured output.
  • Flexible Data Serialization: A generic codec package for serializing data structures, perfect for session data.
  • Built-in Authorization Hooks: Includes a relation package designed to integrate with permission systems like Ory Keto.

Package Overview

Package Description
log A wrapper around Zap for high-performance, structured logging. Configurable for dev/prod environments.
errors A simple utility for creating wrapped, traceable errors.
codec A flexible serialization package (GOB, MessagePack) for encoding/decoding Go types to strings.
db/mgo An abstraction layer for MongoDB that simplifies connection management and promotes self-describing models with automatic index creation.
validate A helper for request validation, used by the gRPC interceptor.
ezgrpc The core of the toolkit. Simplifies gRPC server and gateway setup, including interceptors for logging, metrics, validation, and session management.
relation An interface for managing authorization tuples, designed for systems like Ory Keto.

Getting Started: A Complete Example

This example demonstrates how to build a simple UserService that creates a user and saves it to a database.

1. Define the Database Model (models/user.go)

First, define the User model using the db/mgo package patterns.

package models

import (
	"github.com/94peter/vulpes/db/mgo"
	"github.com/94peter/vulpes/validate"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.mongodb.org/mongo-driver/v2/mongo"
	"go.mongodb.org/mongo-driver/v2/mongo/options"
)

var userCollection = mgo.NewCollectDef("users", func() []mongo.IndexModel {
	return []mongo.IndexModel{
		{Keys: bson.D{{Key: "email", Value: 1}}, Options: options.Index().SetUnique(true)},
	}
})

func init() {
	mgo.RegisterIndex(userCollection)
}

type User struct {
	mgo.Index   `bson:"-"`
	ID        bson.ObjectID `bson:"_id,omitempty"`
	Name      string        `bson:"name" validate:"required"`
	Email     string        `bson:"email" validate:"required,email"`
	Password  string        `bson:"password" validate:"required"`
}

func (u *User) Validate() error {
	return validate.Struct(u)
}

func NewUser(name, email string) *User {
	return &User{
		Index: userCollection,
		ID:    bson.NewObjectID(),
		Name:  name,
		Email: email,
	}
}
2. Define the gRPC Service (proto/user.proto)

Define the service, request, and response messages.

syntax = "proto3";

package user;

option go_package = "path/to/your/user";

import "google/api/annotations.proto";

service UserService {
  rpc CreateUser(CreateUserRequest) returns (CreateUserResponse) {
    option (google.api.http) = {
      post: "/v1/users",
      body: "*"
    };
  }
}

message CreateUserRequest {
  string name = 1;
  string email = 2;
}

message CreateUserResponse {
  string user_id = 1;
}
3. Implement the gRPC Service (services/user.go)

Implement the server logic and register it with ezgrpc.

package services

import (
	"context"

	"github.com/94peter/vulpes/db/mgo"
	"github.com/94peter/vulpes/ezgrpc"
	"github.com/94peter/vulpes/log"
	"path/to/your/models"
	pb "path/to/your/user"
	"google.golang.org/grpc"
)

func init() {
	ezgrpc.InjectGrpcService(func(s *grpc.Server) {
		pb.RegisterUserServiceServer(s, &userService{})
	})
	ezgrpc.RegisterHandlerFromEndpoint(pb.RegisterUserServiceHandlerFromEndpoint)
}

type userService struct {
	pb.UnimplementedUserServiceServer
}

func (s *userService) CreateUser(ctx context.Context, req *pb.CreateUserRequest) (*pb.CreateUserResponse, error) {
	log.Info("Received CreateUser request", log.String("name", req.Name), log.String("email", req.Email))

	user := models.NewUser(req.Name, req.Email)

	if err := user.Validate(); err != nil {
		log.Error("Validation failed", log.Err(err))
		// The validation interceptor in ezgrpc will likely catch this first,
		// but it's good practice to validate here too.
		return nil, err
	}

	userCollection := mgo.GetCollection(user.C())
	_, err := userCollection.InsertOne(ctx, user)
	if err != nil {
		log.Error("Failed to insert user", log.Err(err))
		return nil, err
	}

	log.Info("Successfully created user", log.String("user_id", user.ID.Hex()))

	return &pb.CreateUserResponse{UserId: user.ID.Hex()}, nil
}
4. Tie It All Together (main.go)

Your main function is now incredibly simple. It just needs to initialize the Vulpes packages and run the server.

package main

import (
	"context"
	"log"
	"time"

	"github.com/94peter/vulpes/db/mgo"
	"github.com/94peter/vulpes/ezgrpc"
	vulpeslog "github.com/94peter/vulpes/log"

	// Blank imports to trigger service and model registration
	_ "path/to/your/models"
	_ "path/to/your/services"
)

func main() {
	// 1. Configure logger (optional)
	vulpeslog.SetConfig(vulpeslog.WithDev(true), vulpeslog.WithLevel("debug"))

	// 2. Initialize MongoDB connection
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	if err := mgo.InitConnection(ctx, "myAppDB", mgo.WithURI("mongodb://localhost:27017")); err != nil {
		log.Fatalf("Failed to connect to DB: %v", err)
	}
	defer mgo.Close(ctx)

	// 3. Create database indexes if they don't exist
	if err := mgo.CreateIndexesIfNotExists(ctx); err != nil {
		log.Fatalf("Failed to create indexes: %v", err)
	}

	// 4. Initialize gRPC session store
	ezgrpc.InitSessionStore()

	// 5. Run the gRPC server and gateway
	vulpeslog.Info("Starting server on port 8080")
	if err := ezgrpc.RunGrpcGateway(context.Background(), 8080); err != nil {
		log.Fatalf("Server failed to start: %v", err)
	}
}

Installation

go get github.com/94peter/vulpes/...

Directories

Path Synopsis
Package codec provides a flexible framework for encoding and decoding data structures.
Package codec provides a flexible framework for encoding and decoding data structures.
db
mgo
Package mgo provides a high-level abstraction layer over the official MongoDB Go driver, simplifying connection management, document operations, and schema definitions.
Package mgo provides a high-level abstraction layer over the official MongoDB Go driver, simplifying connection management, document operations, and schema definitions.
mgo/types
Package types provides shared, specialized data types for use with MongoDB documents.
Package types provides shared, specialized data types for use with MongoDB documents.
export
csv
Package ezgrpc provides a simplified setup for gRPC services with a grpc-gateway.
Package ezgrpc provides a simplified setup for gRPC services with a grpc-gateway.
interceptor
Package interceptor provides gRPC unary server interceptors for common concerns such as logging, metrics, rate limiting, and panic recovery.
Package interceptor provides gRPC unary server interceptors for common concerns such as logging, metrics, rate limiting, and panic recovery.
Package log provides a simplified and opinionated interface for structured logging, built on top of the high-performance zap logger.
Package log provides a simplified and opinionated interface for structured logging, built on top of the high-performance zap logger.
Package relation provides a client for Ory Keto, an open-source authorization server.
Package relation provides a client for Ory Keto, an open-source authorization server.
sample command

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL