[DOC] add godoc comments
This commit is contained in:
parent
d780555556
commit
b81c98785a
22
README.md
22
README.md
|
@ -1,20 +1,20 @@
|
||||||
# Stock-Microservice
|
# Stock-Microservice
|
||||||
This is a microservice cutted out of a [Monolith](https://gitlab.com/matthiasstock/monolith).
|
This is a microservice cutted out of a [Monolith](https://gitlab.com/matthiasstock/monolith).
|
||||||
|
|
||||||
[![Build Status](https://travis-ci.org/genofire/hs_master-kss-monolith.svg?branch=master)](https://travis-ci.org/genofire/hs_master-kss-monolith) [![Coverage Status](https://coveralls.io/repos/github/genofire/hs_master-kss-monolith/badge.svg?branch=master)](https://coveralls.io/github/genofire/hs_master-kss-monolith?branch=master)
|
[![Build Status](https://travis-ci.org/genofire/hs_master-kss-monolith.svg?branch=master)](https://travis-ci.org/genofire/hs_master-kss-monolith) [![Coverage Status](https://coveralls.io/repos/github/genofire/hs_master-kss-monolith/badge.svg?branch=master)](https://coveralls.io/github/genofire/hs_master-kss-monolith?branch=master) [![GoDoc](https://godoc.org/github.com/genofire/hs_master-kss-monolith?status.svg)](https://godoc.org/github.com/genofire/hs_master-kss-monolith)
|
||||||
|
|
||||||
## Features of this stock mircoservice
|
## Features of this stock mircoservice
|
||||||
* The main functionality of the microservice is to store the goods with their storage location and a time stamp, when they where stored.
|
* The main functionality of the microservice is to store the goods with their storage location and a time stamp, when they where stored.
|
||||||
* Functionality of the admin frontend
|
* Functionality of the admin frontend
|
||||||
** Add new goods to the stock
|
* Add new goods to the stock
|
||||||
** Manually remove a single goods from the stock, for example when they are rancid
|
* Manually remove a single goods from the stock, for example when they are rancid
|
||||||
** Remove single goods from the stock, when they are send to a costumer
|
* Remove single goods from the stock, when they are send to a costumer
|
||||||
** Block goods from the stock, when a costumer added them to hie cart
|
* Block goods from the stock, when a costumer added them to hie cart
|
||||||
* Functionality of the costumer frontend
|
* Functionality of the costumer frontend
|
||||||
** Show the store with a traffic light food labelling
|
* Show the store with a traffic light food labelling
|
||||||
** A stock of more then seven goods corresponds to the colour green (sufficient amount of goods)
|
* A stock of more then seven goods corresponds to the colour green (sufficient amount of goods)
|
||||||
** A stock between four and seven goods corresponds to the colour orange (moderate amount of goods)
|
* A stock between four and seven goods corresponds to the colour orange (moderate amount of goods)
|
||||||
** A stock between zero and three goods corresponds to the colour red (slim amount of goods)
|
* A stock between zero and three goods corresponds to the colour red (slim amount of goods)
|
||||||
* Optional Features
|
* Optional Features
|
||||||
** Admin frontend: display of a statistic on how many goods where convexed and manually removed from the stock during the last month
|
* Admin frontend: display of a statistic on how many goods where convexed and manually removed from the stock during the last month
|
||||||
** Traffic light food labelling for each good, which indicates whether the good is too old
|
* Traffic light food labelling for each good, which indicates whether the good is too old
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// The cmd binary of the microservice to run
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// all api routes of this microservice
|
||||||
package http
|
package http
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -5,6 +6,7 @@ import (
|
||||||
"goji.io/pat"
|
"goji.io/pat"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// bind all API routes to webserver
|
||||||
func BindAPI(router *goji.Mux) {
|
func BindAPI(router *goji.Mux) {
|
||||||
router.HandleFunc(pat.Get("/api/status"), status)
|
router.HandleFunc(pat.Get("/api/status"), status)
|
||||||
router.HandleFunc(pat.Get("/api/good/:productid"), listGoods)
|
router.HandleFunc(pat.Get("/api/good/:productid"), listGoods)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"text/template"
|
"text/template"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// path to the svg image templaes to show availablity of a given good
|
||||||
var GoodAvailablityTemplate string
|
var GoodAvailablityTemplate string
|
||||||
|
|
||||||
func tempProcent(value, max int) int {
|
func tempProcent(value, max int) int {
|
||||||
|
|
|
@ -10,17 +10,27 @@ import (
|
||||||
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Database connection for writing
|
||||||
|
var Write *gorm.DB
|
||||||
|
|
||||||
|
// Database connection for reading
|
||||||
|
var Read *gorm.DB
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Write *gorm.DB
|
|
||||||
Read *gorm.DB
|
|
||||||
config *Config
|
config *Config
|
||||||
runtime []interface{}
|
runtime []interface{}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// configuration for the database connection
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// type of database: current support sqlite and postgres
|
||||||
|
// (by request other could be enabled)
|
||||||
Type string
|
Type string
|
||||||
|
// connection configuration
|
||||||
Connection string
|
Connection string
|
||||||
|
// maybe create another connection just for reading
|
||||||
ReadConnection string
|
ReadConnection string
|
||||||
|
// enable logging the generated sql string
|
||||||
Logging bool
|
Logging bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ package http
|
||||||
|
|
||||||
import "net/http"
|
import "net/http"
|
||||||
|
|
||||||
|
// format of a function to bind it for the middleware handler
|
||||||
type HasPermission func(string, int) (bool, error)
|
type HasPermission func(string, int) (bool, error)
|
||||||
|
|
||||||
// Function to evaluate the permission and implent an error handling
|
// Function to evaluate the permission and implent an error handling
|
||||||
|
|
|
@ -9,10 +9,9 @@ import (
|
||||||
logger "github.com/Sirupsen/logrus"
|
logger "github.com/Sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// current logger with configuration
|
||||||
var Log *logger.Logger
|
var Log *logger.Logger
|
||||||
|
|
||||||
type Logger logger.Entry
|
|
||||||
|
|
||||||
// Function to initiate a new logger
|
// Function to initiate a new logger
|
||||||
func init() {
|
func init() {
|
||||||
Log = logger.New()
|
Log = logger.New()
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
|
// A little lib for cronjobs to run it in background
|
||||||
package worker
|
package worker
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
|
// a struct which handle the job
|
||||||
type Worker struct {
|
type Worker struct {
|
||||||
every time.Duration
|
every time.Duration
|
||||||
run func()
|
run func()
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a new Worker with timestamp run every and his function
|
||||||
func NewWorker(every time.Duration, f func()) (w *Worker) {
|
func NewWorker(every time.Duration, f func()) (w *Worker) {
|
||||||
w = &Worker{
|
w = &Worker{
|
||||||
every: every,
|
every: every,
|
||||||
|
@ -17,6 +20,8 @@ func NewWorker(every time.Duration, f func()) (w *Worker) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// start the worker
|
||||||
|
// please us it as a goroutine: go w.Start()
|
||||||
func (w *Worker) Start() {
|
func (w *Worker) Start() {
|
||||||
ticker := time.NewTicker(w.every)
|
ticker := time.NewTicker(w.every)
|
||||||
for {
|
for {
|
||||||
|
@ -29,6 +34,8 @@ func (w *Worker) Start() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// stop the worker
|
||||||
func (w *Worker) Close() {
|
func (w *Worker) Close() {
|
||||||
close(w.quit)
|
close(w.quit)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,31 +9,45 @@ import (
|
||||||
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
//Config the config File of this daemon
|
//config file of this daemon (for more the config_example.conf in git repository)
|
||||||
type Config struct {
|
type Config struct {
|
||||||
|
// address on which the api and static content webserver runs
|
||||||
WebserverBind string `toml:"webserver_bind"`
|
WebserverBind string `toml:"webserver_bind"`
|
||||||
|
|
||||||
|
// path to deliver static content
|
||||||
Webroot string `toml:"webroot"`
|
Webroot string `toml:"webroot"`
|
||||||
|
|
||||||
Database database.Config `toml:"database"`
|
Database database.Config `toml:"database"`
|
||||||
GoodRelease GoodReleaseConfig `toml:"good_release"`
|
GoodRelease GoodReleaseConfig `toml:"good_release"`
|
||||||
CacheClean CacheWorkerConfig `toml:"cache_clean"`
|
CacheClean CacheWorkerConfig `toml:"cache_clean"`
|
||||||
|
|
||||||
|
// path to the svg image templaes to show availablity of a given good
|
||||||
GoodAvailablityTemplate string `toml:"good_availablity_template"`
|
GoodAvailablityTemplate string `toml:"good_availablity_template"`
|
||||||
|
|
||||||
|
// URLs to other microservices
|
||||||
MicroserviceDependencies struct {
|
MicroserviceDependencies struct {
|
||||||
Product string `toml:"product"`
|
Product string `toml:"product"`
|
||||||
Permission string `toml:"permission"`
|
Permission string `toml:"permission"`
|
||||||
} `toml:"microservice_dependencies"`
|
} `toml:"microservice_dependencies"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//config of worker to clean caches from values of other microservice
|
||||||
type CacheWorkerConfig struct {
|
type CacheWorkerConfig struct {
|
||||||
|
// run worker every ...
|
||||||
Every Duration
|
Every Duration
|
||||||
|
// remove cache which is not used since ..
|
||||||
After Duration
|
After Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//config of worker to release looked goods after a time
|
||||||
type GoodReleaseConfig struct {
|
type GoodReleaseConfig struct {
|
||||||
After Duration `toml:"after"`
|
// run worker every ...
|
||||||
Every Duration `toml:"every"`
|
Every Duration `toml:"every"`
|
||||||
|
// unlock which is not used since ..
|
||||||
|
After Duration `toml:"after"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ReadConfigFile reads a config model from path of a yml file
|
//reads a config model from path of a yml file
|
||||||
func ReadConfigFile(path string) *Config {
|
func ReadConfigFile(path string) *Config {
|
||||||
config := &Config{}
|
config := &Config{}
|
||||||
file, err := ioutil.ReadFile(path)
|
file, err := ioutil.ReadFile(path)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// this stock microservice manage goods
|
||||||
type Good struct {
|
type Good struct {
|
||||||
ID int64
|
ID int64
|
||||||
ProductID int64
|
ProductID int64
|
||||||
|
@ -25,18 +26,24 @@ type Good struct {
|
||||||
Sended bool
|
Sended bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// generate database select which filtered locked goods
|
||||||
func (g *Good) FilterAvailable(db *gorm.DB) *gorm.DB {
|
func (g *Good) FilterAvailable(db *gorm.DB) *gorm.DB {
|
||||||
return db.Model(g).Where("locked_secret == '' OR locked_secret is NULL")
|
return db.Model(g).Where("locked_secret == '' OR locked_secret is NULL")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lock the good, on a way, that it could not be used by other users
|
||||||
func (g *Good) Lock(secret string) {
|
func (g *Good) Lock(secret string) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
g.LockedSecret = secret
|
g.LockedSecret = secret
|
||||||
g.LockedAt = &now
|
g.LockedAt = &now
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// is this good locked?
|
||||||
func (g *Good) IsLock() bool {
|
func (g *Good) IsLock() bool {
|
||||||
return len(g.LockedSecret) > 0
|
return len(g.LockedSecret) > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// unlock the good, that it could be usered again
|
||||||
func (g *Good) Unlock(secret string) error {
|
func (g *Good) Unlock(secret string) error {
|
||||||
if g.LockedSecret == secret {
|
if g.LockedSecret == secret {
|
||||||
g.LockedSecret = ""
|
g.LockedSecret = ""
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
// a package to store all the struct
|
||||||
|
package models
|
|
@ -8,12 +8,19 @@ import (
|
||||||
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// url to the microservice which manage the permissions
|
||||||
var PermissionURL string
|
var PermissionURL string
|
||||||
|
|
||||||
|
// type of permission
|
||||||
type Permission int
|
type Permission int
|
||||||
|
|
||||||
|
// some permission (see Permission)
|
||||||
const (
|
const (
|
||||||
|
// has the user the permission to create need goods of a product
|
||||||
|
// e.g. if a good received and now availablity to sell
|
||||||
PermissionCreateGood = 1
|
PermissionCreateGood = 1
|
||||||
|
// has the user the permission to delete need goods of a product
|
||||||
|
// e.g. if a good become rancid and has to remove from stock
|
||||||
PermissionDeleteGood = 2
|
PermissionDeleteGood = 2
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -49,6 +56,7 @@ func init() {
|
||||||
permissionCache = make(map[string]*permissionMicroServiceCache)
|
permissionCache = make(map[string]*permissionMicroServiceCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if the client with the session string has a permissions (see Permission)
|
||||||
func HasPermission(session string, p Permission) (bool, error) {
|
func HasPermission(session string, p Permission) (bool, error) {
|
||||||
_, ok := permissionCache[session]
|
_, ok := permissionCache[session]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -7,8 +7,10 @@ import (
|
||||||
"github.com/genofire/hs_master-kss-monolith/models"
|
"github.com/genofire/hs_master-kss-monolith/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// config of the cache worker
|
||||||
var CacheConfig models.CacheWorkerConfig
|
var CacheConfig models.CacheWorkerConfig
|
||||||
|
|
||||||
|
// command which is runned in the cache worker
|
||||||
func CleanCache() {
|
func CleanCache() {
|
||||||
before := time.Now().Add(-CacheConfig.After.Duration)
|
before := time.Now().Add(-CacheConfig.After.Duration)
|
||||||
// Cache if product exists
|
// Cache if product exists
|
||||||
|
@ -24,6 +26,8 @@ func CleanCache() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create a worker to clean the caches which stored from other microservice
|
||||||
func NewCacheWorker() (w *worker.Worker) {
|
func NewCacheWorker() (w *worker.Worker) {
|
||||||
return worker.NewWorker(CacheConfig.Every.Duration, CleanCache)
|
return worker.NewWorker(CacheConfig.Every.Duration, CleanCache)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/genofire/hs_master-kss-monolith/models"
|
"github.com/genofire/hs_master-kss-monolith/models"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// create a worker to unlock goods which are locked by clients
|
||||||
func NewGoodReleaseWorker(grc models.GoodReleaseConfig) *worker.Worker {
|
func NewGoodReleaseWorker(grc models.GoodReleaseConfig) *worker.Worker {
|
||||||
return worker.NewWorker(grc.Every.Duration, func() {
|
return worker.NewWorker(grc.Every.Duration, func() {
|
||||||
goodRelease(grc.After.Duration)
|
goodRelease(grc.After.Duration)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
// some functionality to handle it in background which is intermeshed
|
||||||
|
package runtime
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// url to the microservice which manage the products
|
||||||
var ProductURL string
|
var ProductURL string
|
||||||
|
|
||||||
type boolMicroServiceCache struct {
|
type boolMicroServiceCache struct {
|
||||||
|
@ -21,6 +22,7 @@ func init() {
|
||||||
productExistCache = make(map[int64]boolMicroServiceCache)
|
productExistCache = make(map[int64]boolMicroServiceCache)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check on the other microservice if the product exists
|
||||||
func ProductExists(id int64) (bool, error) {
|
func ProductExists(id int64) (bool, error) {
|
||||||
if cache, ok := productExistCache[id]; ok {
|
if cache, ok := productExistCache[id]; ok {
|
||||||
return cache.Value, nil
|
return cache.Value, nil
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
// A little lib to easy create everything for running virtual api
|
||||||
package test
|
package test
|
||||||
|
|
||||||
// Request an easy manager to test REST-API
|
// Request an easy manager to test REST-API
|
||||||
|
@ -16,7 +17,7 @@ import (
|
||||||
|
|
||||||
var srv *http.Server
|
var srv *http.Server
|
||||||
|
|
||||||
//Init to initialisieren an API
|
//initialisieren an API test api
|
||||||
func Init(t *testing.T) (assertion *assert.Assertions, router *goji.Mux) {
|
func Init(t *testing.T) (assertion *assert.Assertions, router *goji.Mux) {
|
||||||
assertion = assert.New(t)
|
assertion = assert.New(t)
|
||||||
database.Open(database.Config{
|
database.Open(database.Config{
|
||||||
|
@ -35,15 +36,18 @@ func Init(t *testing.T) (assertion *assert.Assertions, router *goji.Mux) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close just the static webserver (with test files of other microservice)
|
||||||
func CloseServer() {
|
func CloseServer() {
|
||||||
srv.Close()
|
srv.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// close everything
|
||||||
func Close() {
|
func Close() {
|
||||||
database.Close()
|
database.Close()
|
||||||
srv.Close()
|
srv.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handle a test client session with cookies
|
||||||
type Request struct {
|
type Request struct {
|
||||||
req *http.Request
|
req *http.Request
|
||||||
cookies []*http.Cookie
|
cookies []*http.Cookie
|
||||||
|
@ -55,7 +59,7 @@ func NewSession(router *goji.Mux) *Request {
|
||||||
return &Request{router: router}
|
return &Request{router: router}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSONRequest send request to router
|
// send request to router and recieve the api answer
|
||||||
func (r *Request) JSONRequest(method string, url string, body interface{}) (jsonResult interface{}, res *http.Response) {
|
func (r *Request) JSONRequest(method string, url string, body interface{}) (jsonResult interface{}, res *http.Response) {
|
||||||
jsonObj, _ := json.Marshal(body)
|
jsonObj, _ := json.Marshal(body)
|
||||||
req, _ := http.NewRequest(method, url, bytes.NewReader(jsonObj))
|
req, _ := http.NewRequest(method, url, bytes.NewReader(jsonObj))
|
||||||
|
@ -75,7 +79,7 @@ func (r *Request) JSONRequest(method string, url string, body interface{}) (json
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean to clean the current session
|
// clean the current session
|
||||||
func (r *Request) Clean() {
|
func (r *Request) Clean() {
|
||||||
r.cookies = nil
|
r.cookies = nil
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue