[TASK] delete good and fouled timer
This commit is contained in:
parent
64379f77ad
commit
b6ade49a41
|
@ -7,11 +7,13 @@ import (
|
|||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/NYTimes/gziphandler"
|
||||
goji "goji.io"
|
||||
"goji.io/pat"
|
||||
|
||||
"github.com/genofire/golang-lib/worker"
|
||||
web "github.com/genofire/hs_master-kss-monolith/http"
|
||||
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
||||
"github.com/genofire/hs_master-kss-monolith/lib/log"
|
||||
|
@ -48,8 +50,12 @@ func main() {
|
|||
}
|
||||
grw := runtime.NewGoodReleaseWorker(config.GoodRelease)
|
||||
cw := runtime.NewCacheWorker()
|
||||
fw := worker.NewWorker(config.FouledDeleter.Duration, func() { runtime.GoodFouled() })
|
||||
go grw.Start()
|
||||
go cw.Start()
|
||||
if config.FouledDeleter.Duration != time.Duration(0) {
|
||||
go fw.Start()
|
||||
}
|
||||
// Startwebsrver
|
||||
router := goji.NewMux()
|
||||
web.BindAPI(router)
|
||||
|
@ -77,6 +83,7 @@ func main() {
|
|||
srv.Close()
|
||||
grw.Close()
|
||||
cw.Close()
|
||||
fw.Close()
|
||||
database.Close()
|
||||
|
||||
log.Log.Info("received", sig)
|
||||
|
|
|
@ -4,6 +4,8 @@ webroot = "webroot"
|
|||
good_availablity_template = "contrib/good_availablity.svg"
|
||||
good_freshness_template = "contrib/good_freshness.svg"
|
||||
|
||||
fouled_deleted = "0m"
|
||||
|
||||
[database]
|
||||
type = "sqlite3"
|
||||
# logging = true
|
||||
|
|
|
@ -16,4 +16,5 @@ func BindAPI(router *goji.Mux) {
|
|||
router.HandleFunc(pat.Get("/api/good/availablity/:productid"), getGoodAvailability)
|
||||
router.HandleFunc(pat.Get("/api/good/freshness/:goodid"), getGoodFreshness)
|
||||
router.HandleFunc(pat.Post("/api/good/:productid"), http.PermissionHandler(addGood, runtime.HasPermission, runtime.PermissionCreateGood))
|
||||
router.HandleFunc(pat.Delete("/api/good/:goodid"), http.PermissionHandler(delGood, runtime.HasPermission, runtime.PermissionDeleteGood))
|
||||
}
|
||||
|
|
30
http/good.go
30
http/good.go
|
@ -4,6 +4,7 @@ package http
|
|||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"goji.io/pat"
|
||||
|
||||
|
@ -55,3 +56,32 @@ func addGood(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
log.Info("done")
|
||||
}
|
||||
|
||||
// Function that returns the freshness of a good
|
||||
func delGood(w http.ResponseWriter, r *http.Request) {
|
||||
log := logger.HTTP(r)
|
||||
id, err := strconv.ParseInt(pat.Param(r, "goodid"), 10, 64)
|
||||
if err != nil {
|
||||
log.Warn("wrong goodid format")
|
||||
http.Error(w, "the good id has a false format", http.StatusNotAcceptable)
|
||||
return
|
||||
}
|
||||
log = log.WithField("goodid", id)
|
||||
|
||||
now := time.Now()
|
||||
var good models.Good
|
||||
good.ID = id
|
||||
good.ManuelleDelete = true
|
||||
good.DeletedAt = &now
|
||||
db := database.Write.Save(&good)
|
||||
if db.Error != nil {
|
||||
log.Warnf("good could not delete: %s", db.Error)
|
||||
http.Error(w, "the good could not delete", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if db.RowsAffected != 1 {
|
||||
log.Warnf("good could not found: %s", db.Error)
|
||||
http.Error(w, "the good could not found", http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -72,3 +72,45 @@ func TestAddGood(t *testing.T) {
|
|||
|
||||
test.Close()
|
||||
}
|
||||
|
||||
// Function to test delGood()
|
||||
func TestDelGood(t *testing.T) {
|
||||
assertion, router := test.Init(t)
|
||||
|
||||
BindAPI(router)
|
||||
runtime.PermissionURL = "http://localhost:8080/api-test/session/%s/%d/"
|
||||
session := test.NewSession(router)
|
||||
|
||||
good := models.Good{
|
||||
ID: 3,
|
||||
Comment: "blub",
|
||||
}
|
||||
|
||||
database.Write.Create(&good)
|
||||
|
||||
_, w := session.JSONRequest("DELETE", "/api/good/1", nil)
|
||||
assertion.Equal(http.StatusNonAuthoritativeInfo, w.StatusCode)
|
||||
|
||||
session.Login()
|
||||
|
||||
_, w = session.JSONRequest("DELETE", "/api/good/a", nil)
|
||||
assertion.Equal(http.StatusNotAcceptable, w.StatusCode)
|
||||
|
||||
_, w = session.JSONRequest("DELETE", "/api/good/3", nil)
|
||||
assertion.Equal(http.StatusOK, w.StatusCode)
|
||||
|
||||
_, w = session.JSONRequest("DELETE", "/api/good/3", nil)
|
||||
assertion.Equal(http.StatusNotFound, w.StatusCode)
|
||||
|
||||
database.Close()
|
||||
|
||||
_, w = session.JSONRequest("DELETE", "/api/good/1", nil)
|
||||
assertion.Equal(http.StatusInternalServerError, w.StatusCode)
|
||||
|
||||
session.Logout()
|
||||
|
||||
_, w = session.JSONRequest("DELETE", "/api/good/1", nil)
|
||||
assertion.Equal(http.StatusForbidden, w.StatusCode)
|
||||
|
||||
test.Close()
|
||||
}
|
||||
|
|
|
@ -13,20 +13,22 @@ import (
|
|||
// Config file for this daemon (more information at the config_example.conf in this git repository)
|
||||
type Config struct {
|
||||
// address under which the api and static content of the 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"`
|
||||
GoodRelease GoodReleaseConfig `toml:"good_release"`
|
||||
CacheClean CacheWorkerConfig `toml:"cache_clean"`
|
||||
Database database.Config `toml:"database"`
|
||||
GoodRelease GoodReleaseConfig `toml:"good_release"`
|
||||
CacheClean CacheWorkerConfig `toml:"cache_clean"`
|
||||
|
||||
// path to the svg image templates to show the availablity and freshness
|
||||
// of a given good with a traffic light food labeling system
|
||||
GoodAvailabilityTemplate string `toml:"good_availablity_template"`
|
||||
GoodFreshnessTemplate string `toml:"good_freshness_template"`
|
||||
|
||||
FouledDeleter Duration `toml:"fouled_deleted"`
|
||||
|
||||
// URLs to other microservices that this services uses
|
||||
MicroserviceDependencies struct {
|
||||
Product string `toml:"product"`
|
||||
|
|
|
@ -23,8 +23,9 @@ type Good struct {
|
|||
LockedAt *time.Time `json:"-"`
|
||||
LockedSecret string `json:"-"`
|
||||
// Make it unusable
|
||||
DeletedAt *time.Time `json:"-"`
|
||||
Sended bool `json:"-"`
|
||||
DeletedAt *time.Time `json:"-"`
|
||||
ManuelleDelete bool `json:"-"`
|
||||
FouledDelete bool `json:"-"`
|
||||
}
|
||||
|
||||
// Function to generate a database and select locked goods with a filter
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
// Package with supporting functionality to run the microservice
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
||||
"github.com/genofire/hs_master-kss-monolith/models"
|
||||
)
|
||||
|
||||
// Function to remove automaticle goods after the are fouled
|
||||
func GoodFouled() int {
|
||||
var goods []*models.Good
|
||||
var g models.Good
|
||||
g.FilterAvailable(database.Read).Where("fouled_at <= ?", time.Now()).Find(&goods)
|
||||
now := time.Now()
|
||||
|
||||
for _, good := range goods {
|
||||
good.FouledDelete = true
|
||||
good.DeletedAt = &now
|
||||
database.Write.Save(&good)
|
||||
}
|
||||
return len(goods)
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// Package with supporting functionality to run the microservice
|
||||
package runtime
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/genofire/hs_master-kss-monolith/lib/database"
|
||||
"github.com/genofire/hs_master-kss-monolith/models"
|
||||
)
|
||||
|
||||
// Function to test the unlocking of goods
|
||||
func TestFouledDelete(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
database.Open(database.Config{
|
||||
Type: "sqlite3",
|
||||
Logging: true,
|
||||
Connection: ":memory:",
|
||||
})
|
||||
|
||||
now := time.Now().Add(-time.Hour * 48)
|
||||
good := models.Good{
|
||||
FouledAt: &now,
|
||||
}
|
||||
database.Write.Create(&good)
|
||||
|
||||
good = models.Good{
|
||||
FouledAt: &now,
|
||||
}
|
||||
database.Write.Create(&good)
|
||||
|
||||
count := GoodFouled()
|
||||
assert.Equal(2, count, "not fouled")
|
||||
|
||||
good = models.Good{
|
||||
FouledAt: &now,
|
||||
}
|
||||
database.Write.Create(&good)
|
||||
|
||||
now = time.Now().Add(time.Hour * 48)
|
||||
good = models.Good{
|
||||
FouledAt: &now,
|
||||
}
|
||||
database.Write.Create(&good)
|
||||
|
||||
count = GoodFouled()
|
||||
assert.Equal(1, count, "fouled")
|
||||
|
||||
database.Close()
|
||||
}
|
|
@ -12,12 +12,12 @@ import (
|
|||
// Function to create a Worker and to unlock goods
|
||||
func NewGoodReleaseWorker(grc models.GoodReleaseConfig) *worker.Worker {
|
||||
return worker.NewWorker(grc.Every.Duration, func() {
|
||||
goodRelease(grc.After.Duration)
|
||||
GoodRelease(grc.After.Duration)
|
||||
})
|
||||
}
|
||||
|
||||
// Function to unlock goods after a specified time
|
||||
func goodRelease(unlockAfter time.Duration) int64 {
|
||||
func GoodRelease(unlockAfter time.Duration) int64 {
|
||||
res := database.Write.Model(&models.Good{}).Where("locked_secret is not NULL and locked_at < ?", time.Now().Add(-unlockAfter)).Updates(map[string]interface{}{"locked_secret": "", "locked_at": nil})
|
||||
return res.RowsAffected
|
||||
}
|
||||
|
|
|
@ -25,13 +25,13 @@ func TestGoodRelease(t *testing.T) {
|
|||
LockedSecret: "never used",
|
||||
}
|
||||
database.Write.Create(&good)
|
||||
count := goodRelease(time.Duration(3) * time.Second)
|
||||
count := GoodRelease(time.Duration(3) * time.Second)
|
||||
assert.Equal(int64(0), count, "no locked in timeout")
|
||||
|
||||
older := now.Add(-time.Duration(10) * time.Minute)
|
||||
good.LockedAt = &older
|
||||
database.Write.Save(&good)
|
||||
count = goodRelease(time.Duration(3) * time.Second)
|
||||
count = GoodRelease(time.Duration(3) * time.Second)
|
||||
assert.Equal(int64(1), count, "unlock after timeout")
|
||||
|
||||
grw := NewGoodReleaseWorker(models.GoodReleaseConfig{
|
||||
|
@ -41,4 +41,6 @@ func TestGoodRelease(t *testing.T) {
|
|||
go grw.Start()
|
||||
time.Sleep(time.Duration(15) * time.Millisecond)
|
||||
grw.Close()
|
||||
|
||||
database.Close()
|
||||
}
|
||||
|
|
Reference in New Issue