genofire/hs_monolith
genofire
/
hs_monolith
Archived
1
0
Fork 0

[TASK] delete good and fouled timer

This commit is contained in:
Martin Geno 2017-05-18 23:42:00 +02:00
parent 64379f77ad
commit b6ade49a41
No known key found for this signature in database
GPG Key ID: F0D39A37E925E941
11 changed files with 174 additions and 11 deletions

View File

@ -7,11 +7,13 @@ import (
"os" "os"
"os/signal" "os/signal"
"syscall" "syscall"
"time"
"github.com/NYTimes/gziphandler" "github.com/NYTimes/gziphandler"
goji "goji.io" goji "goji.io"
"goji.io/pat" "goji.io/pat"
"github.com/genofire/golang-lib/worker"
web "github.com/genofire/hs_master-kss-monolith/http" 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/database"
"github.com/genofire/hs_master-kss-monolith/lib/log" "github.com/genofire/hs_master-kss-monolith/lib/log"
@ -48,8 +50,12 @@ func main() {
} }
grw := runtime.NewGoodReleaseWorker(config.GoodRelease) grw := runtime.NewGoodReleaseWorker(config.GoodRelease)
cw := runtime.NewCacheWorker() cw := runtime.NewCacheWorker()
fw := worker.NewWorker(config.FouledDeleter.Duration, func() { runtime.GoodFouled() })
go grw.Start() go grw.Start()
go cw.Start() go cw.Start()
if config.FouledDeleter.Duration != time.Duration(0) {
go fw.Start()
}
// Startwebsrver // Startwebsrver
router := goji.NewMux() router := goji.NewMux()
web.BindAPI(router) web.BindAPI(router)
@ -77,6 +83,7 @@ func main() {
srv.Close() srv.Close()
grw.Close() grw.Close()
cw.Close() cw.Close()
fw.Close()
database.Close() database.Close()
log.Log.Info("received", sig) log.Log.Info("received", sig)

View File

@ -4,6 +4,8 @@ webroot = "webroot"
good_availablity_template = "contrib/good_availablity.svg" good_availablity_template = "contrib/good_availablity.svg"
good_freshness_template = "contrib/good_freshness.svg" good_freshness_template = "contrib/good_freshness.svg"
fouled_deleted = "0m"
[database] [database]
type = "sqlite3" type = "sqlite3"
# logging = true # logging = true

View File

@ -16,4 +16,5 @@ func BindAPI(router *goji.Mux) {
router.HandleFunc(pat.Get("/api/good/availablity/:productid"), getGoodAvailability) router.HandleFunc(pat.Get("/api/good/availablity/:productid"), getGoodAvailability)
router.HandleFunc(pat.Get("/api/good/freshness/:goodid"), getGoodFreshness) 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.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))
} }

View File

@ -4,6 +4,7 @@ package http
import ( import (
"net/http" "net/http"
"strconv" "strconv"
"time"
"goji.io/pat" "goji.io/pat"
@ -55,3 +56,32 @@ func addGood(w http.ResponseWriter, r *http.Request) {
log.Info("done") 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
}
}

View File

@ -72,3 +72,45 @@ func TestAddGood(t *testing.T) {
test.Close() 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()
}

View File

@ -13,20 +13,22 @@ import (
// Config file for this daemon (more information at the config_example.conf in this git repository) // Config file for this daemon (more information at the config_example.conf in this git repository)
type Config struct { type Config struct {
// address under which the api and static content of the webserver runs // 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 // 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 templates to show the availablity and freshness // path to the svg image templates to show the availablity and freshness
// of a given good with a traffic light food labeling system // of a given good with a traffic light food labeling system
GoodAvailabilityTemplate string `toml:"good_availablity_template"` GoodAvailabilityTemplate string `toml:"good_availablity_template"`
GoodFreshnessTemplate string `toml:"good_freshness_template"` GoodFreshnessTemplate string `toml:"good_freshness_template"`
FouledDeleter Duration `toml:"fouled_deleted"`
// URLs to other microservices that this services uses // URLs to other microservices that this services uses
MicroserviceDependencies struct { MicroserviceDependencies struct {
Product string `toml:"product"` Product string `toml:"product"`

View File

@ -23,8 +23,9 @@ type Good struct {
LockedAt *time.Time `json:"-"` LockedAt *time.Time `json:"-"`
LockedSecret string `json:"-"` LockedSecret string `json:"-"`
// Make it unusable // Make it unusable
DeletedAt *time.Time `json:"-"` DeletedAt *time.Time `json:"-"`
Sended bool `json:"-"` ManuelleDelete bool `json:"-"`
FouledDelete bool `json:"-"`
} }
// Function to generate a database and select locked goods with a filter // Function to generate a database and select locked goods with a filter

24
runtime/good_fouled.go Normal file
View File

@ -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)
}

View File

@ -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()
}

View File

@ -12,12 +12,12 @@ import (
// Function to create a Worker and to unlock goods // Function to create a Worker and to unlock goods
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)
}) })
} }
// Function to unlock goods after a specified time // 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}) 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 return res.RowsAffected
} }

View File

@ -25,13 +25,13 @@ func TestGoodRelease(t *testing.T) {
LockedSecret: "never used", LockedSecret: "never used",
} }
database.Write.Create(&good) 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") assert.Equal(int64(0), count, "no locked in timeout")
older := now.Add(-time.Duration(10) * time.Minute) older := now.Add(-time.Duration(10) * time.Minute)
good.LockedAt = &older good.LockedAt = &older
database.Write.Save(&good) 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") assert.Equal(int64(1), count, "unlock after timeout")
grw := NewGoodReleaseWorker(models.GoodReleaseConfig{ grw := NewGoodReleaseWorker(models.GoodReleaseConfig{
@ -41,4 +41,6 @@ func TestGoodRelease(t *testing.T) {
go grw.Start() go grw.Start()
time.Sleep(time.Duration(15) * time.Millisecond) time.Sleep(time.Duration(15) * time.Millisecond)
grw.Close() grw.Close()
database.Close()
} }