Skip to content

๐Ÿ“ A minimal working example for microservices in the WISdoM Architecture

Notifications You must be signed in to change notification settings

wisdom-oss/microservice-template

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

Caution

This repository either is the template for new microservices or this repository has been generated from the template repository.

Microservice Template/Example

service-example

๐Ÿ“ A minimal working example for microservices in the WISdoM Architecture

Go Lang Version Open
API Schema Version

This repository contains a template for new microservices inside the WISdoM architecture. It already handles the connection to the database using the internal/db package and the included init function in that package. To start writing a new microservice you only need to create the new routes in the routes directory and add them to the gin-gonic/gin router used in the project.

Authorization

The microservice automatically disables the authorization in local development scenarios to reduce the hassle with needing a living access token for each request. However, the authorization is enabled when building the Docker Image as it uses the docker build tag which triggers the inclusion of internal/config/docker.go and the exclusion of internal/config/debug.go into the binary.

Tip

To test the authorization you need to manually add the build tag to your build command -tags docker and populate the OIDC_AUTHORITY environment variable which should contain the issuer of the access tokens used in your WISdoM platform, otherwise the startup of the microservice will fail or you may be unable to access the microservice

Using the database

Important

You need to set the following environment variables for a successful connection to the database:

  • PGUSER
  • PGPASSWORD
  • PGHOST
  • PGDATABASE

and optionally the following variables

  • PGPORT

As the database is automatically connected, you don't need to handle this by yourself. To use the database in your code either request a single connection from the connection pool (db.Pool.Acquire) or pass the pool into a supported function (recommended)

Furthermore, all queries stored in the resources folder are embedded into the built executable and available in the db.Queries object, which is a qustavo/dotsql DotSql object which allows recalling queries by their name.

Returning errors to End-Users

Since the router already comes pre-configured with some error handling middleware, sending errors generated by other functions back to an end-user is easy. Just call c.Abort() and c.Error() in your handler and return from the function. The end-user will automatically receive a RFC 9457-compliant error message generated from your output. The following example shows how to output an error and what the expected output should look like on the end-users side:

package routes

import "github.com/gin-gonic/gin"

func BasicHandler(c *gin.Context) {
	// ... your other code which generated an error
	if err != nil {
		c.Abort()
		_ = c.Error(err)
		return
	}

}
HTTP/1.1 500 Internal Server Error
Content-Type: application/problem+json; charset=utf-8
X-Request-Id: 6215ec23-45f9-4182-b848-64a969e7d0c5
Content-Length: 319

[
  {
    "type": "https://www.rfc-editor.org/rfc/rfc9110#section-15.6.1",
    "status": 500,
    "title": "Internal Server Error",
    "detail": "The service encountered an internal error during the handling of your request",
    "instance": "tag:xxxxxxxx,2024-10-15:InternalServerError:1728985891",
    "errors": [
      "error"
    ],
    "host": "xxxxxxxx"
  }
]

If you want to send errors that are generated by your code and are predictable (for example, an object isn't found) should create a types.ServiceError for the error message and send that one back using .Emit() on the created ServiceError object

package routes

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/wisdom-oss/common-go/v2/types"
)

var ObjectNotFoundError types.ServiceError = types.ServiceError{
	Type:   "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.5",
	Status: http.StatusNotFound,
	Title:  "Object Not Found",
	Detail: "The requested object does not exist. Please check the object id",
}

func BasicHandler(c *gin.Context) {
	// ... your other code possibly populating the object
	if object == nil {
		c.Abort()
		ObjectNotFoundError.Emit(c)
		return
	}
}
HTTP/1.1 404 Not Found
Content-Type: application/problem+json; charset=utf-8
X-Request-Id: 82f0e83e-f485-4aca-8706-d0d57ee1585d
Content-Length: 317

{
  "type": "https://www.rfc-editor.org/rfc/rfc9110.html#section-15.5.5",
  "status": 404,
  "title": "Object Not Found",
  "detail": "The requested object does not exist. Please check the object id",
  "instance": "tag:xxxxxxxx,2024-10-15:ObjectNotFound:1728986473",
  "host": "xxxxxxxx"
}

About

๐Ÿ“ A minimal working example for microservices in the WISdoM Architecture

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages