Add ring log + 429

This commit is contained in:
daru
2022-05-13 22:33:59 +02:00
parent b3c152e7b1
commit bbf99fadb4
9 changed files with 163 additions and 25 deletions

2
go.mod
View File

@@ -15,7 +15,7 @@ require (
require ( require (
github.com/andybalholm/brotli v1.0.4 // indirect github.com/andybalholm/brotli v1.0.4 // indirect
github.com/bwmarrin/snowflake v0.3.0 // indirect github.com/bwmarrin/snowflake v0.3.0 // indirect
github.com/klauspost/compress v1.15.3 // indirect github.com/klauspost/compress v1.15.4 // indirect
github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 // indirect github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect

2
go.sum
View File

@@ -20,6 +20,8 @@ github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47e
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.3 h1:wmfu2iqj9q22SyMINp1uQ8C2/V4M1phJdmH9fG4nba0= github.com/klauspost/compress v1.15.3 h1:wmfu2iqj9q22SyMINp1uQ8C2/V4M1phJdmH9fG4nba0=
github.com/klauspost/compress v1.15.3/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/klauspost/compress v1.15.3/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/klauspost/compress v1.15.4 h1:1kn4/7MepF/CHmYub99/nNX8az0IJjfSOU/jbnTVfqQ=
github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 h1:sfTahD3f2BSjx9U3R4K09PkNuZZWthT7g6vzTIXNWkM= github.com/savsgio/gotils v0.0.0-20220401102855-e56b59f40436 h1:sfTahD3f2BSjx9U3R4K09PkNuZZWthT7g6vzTIXNWkM=

View File

@@ -2,6 +2,7 @@ package main
import ( import (
"flag" "flag"
"fmt"
"log" "log"
"os" "os"
"os/signal" "os/signal"
@@ -46,6 +47,7 @@ var (
animeListCache *bigcache.BigCache animeListCache *bigcache.BigCache
db *nutsdb.DB db *nutsdb.DB
jikanLimiter *rate.Limiter jikanLimiter *rate.Limiter
logOut *RingBuf
) )
func main() { func main() {
@@ -55,9 +57,12 @@ func main() {
sc := make(chan os.Signal, 1) sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt) signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM, os.Interrupt)
color.Notice.Printf("huso %s %s\n", husoVersion, runtime.Version()) logOut = NewRingBuf(1000)
jikanLimiter = rate.NewLimiter(rate.Every(time.Second), 2) color.Notice.Printf("huso %s %s\n", husoVersion, runtime.Version())
logOut.WriteLine(fmt.Sprintf("huso %s %s", husoVersion, runtime.Version()))
jikanLimiter = rate.NewLimiter(rate.Every(time.Second), 1)
// cache init // cache init
var err error var err error

View File

@@ -118,11 +118,13 @@ func GetUserData(username string) (*User, []byte, error) {
func GetSeasonDataAll() ([]Anime, []byte, error) { func GetSeasonDataAll() ([]Anime, []byte, error) {
color.Infoln("Aktuelle Season abfragen...") color.Infoln("Aktuelle Season abfragen...")
logOut.WriteLine("Aktuelle Season abfragen...")
data, _, err := GetSeasonData(1) data, _, err := GetSeasonData(1)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
color.Infof("%d Anime auf %d Seiten\n", data.Pagination.Items.Total, data.Pagination.LastVisiblePage) color.Infof("%d Anime auf %d Seiten\n", data.Pagination.Items.Total, data.Pagination.LastVisiblePage)
logOut.WriteLine(fmt.Sprintf("%d Anime auf %d Seiten", data.Pagination.Items.Total, data.Pagination.LastVisiblePage))
animes := make([]Anime, 0) animes := make([]Anime, 0)
// convert to anime // convert to anime
for _, a := range data.Data { for _, a := range data.Data {
@@ -130,7 +132,7 @@ func GetSeasonDataAll() ([]Anime, []byte, error) {
} }
for i := 2; data.Pagination.HasNextPage; i++ { for i := 2; data.Pagination.HasNextPage; i++ {
color.Infof("Seite %d abfragen...\n", i) color.Infof("Seite %d abfragen...\n", i)
time.Sleep(time.Second) logOut.WriteLine(fmt.Sprintf("Seite %d abfragen...", i))
newData, _, err := GetSeasonData(i) newData, _, err := GetSeasonData(i)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
@@ -144,6 +146,7 @@ func GetSeasonDataAll() ([]Anime, []byte, error) {
} }
} }
color.Infof("%d Anime bekommen\n", len(animes)) color.Infof("%d Anime bekommen\n", len(animes))
logOut.WriteLine(fmt.Sprintf("%d Anime bekommen", len(animes)))
bytes, err := json.Marshal(animes) bytes, err := json.Marshal(animes)
return animes, bytes, err return animes, bytes, err
} }

View File

@@ -19,6 +19,7 @@ func RunWebserv() {
r.GET("/api/auth/{user}", Headers(AuthTest)) r.GET("/api/auth/{user}", Headers(AuthTest))
r.GET("/api/anime/{id}", Headers(AnimeGet)) r.GET("/api/anime/{id}", Headers(AnimeGet))
r.GET("/api/animesearch", Headers(AnimeSearchGet)) r.GET("/api/animesearch", Headers(AnimeSearchGet))
r.GET("/api/appointment", Headers(AppointmentGet))
r.GET("/api/user/{user?}", Headers(UserGet)) r.GET("/api/user/{user?}", Headers(UserGet))
r.GET("/api/watch/{user?}", Headers(WatchGet)) r.GET("/api/watch/{user?}", Headers(WatchGet))
r.GET("/api/watchext/{user?}", Headers(WatchExtendedGet)) r.GET("/api/watchext/{user?}", Headers(WatchExtendedGet))
@@ -36,7 +37,7 @@ func Start(ctx *fasthttp.RequestCtx) {
return return
} }
WriteIndex(ctx, season) WriteIndex(ctx, season, logOut.String())
ctx.SetContentType("text/html; charset=utf-8") ctx.SetContentType("text/html; charset=utf-8")
ctx.SetStatusCode(fasthttp.StatusOK) ctx.SetStatusCode(fasthttp.StatusOK)
@@ -135,6 +136,10 @@ func AnimeSearchGet(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusOK) ctx.SetStatusCode(fasthttp.StatusOK)
} }
func AppointmentGet(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fasthttp.StatusNotImplemented)
}
func UserGet(ctx *fasthttp.RequestCtx) { func UserGet(ctx *fasthttp.RequestCtx) {
usrVal := ctx.UserValue("user") usrVal := ctx.UserValue("user")
users := make([]User, 0) users := make([]User, 0)

View File

@@ -2,6 +2,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt"
"strconv" "strconv"
"time" "time"
@@ -20,10 +21,12 @@ func Arbeit() {
_, bytes, err := GetSeasonDataAll() _, bytes, err := GetSeasonDataAll()
if err != nil { if err != nil {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
} else { } else {
err = seasoncache.Set(seasonApiJikan, bytes) err = seasoncache.Set(seasonApiJikan, bytes)
if err != nil { if err != nil {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
} }
} }
// refresh animelist of users // refresh animelist of users
@@ -31,6 +34,7 @@ func Arbeit() {
if err != nil { if err != nil {
if err != nutsdb.ErrBucketEmpty { if err != nutsdb.ErrBucketEmpty {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
} }
return return
} }
@@ -41,6 +45,7 @@ func Arbeit() {
newProgress, updated, err := FetchProgress(a.Anime, u.MalID, u.Username, u.Progress) newProgress, updated, err := FetchProgress(a.Anime, u.MalID, u.Username, u.Progress)
if err != nil { if err != nil {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
continue continue
} }
if newProgress == u.Progress { if newProgress == u.Progress {
@@ -48,9 +53,11 @@ func Arbeit() {
} }
// update db // update db
color.Infof("%s progress von %d: %d -> %d\n", u.Username, a.Anime, u.Progress, newProgress) color.Infof("%s progress von %d: %d -> %d\n", u.Username, a.Anime, u.Progress, newProgress)
logOut.WriteLine(fmt.Sprintf("%s progress von %d: %d -> %d", u.Username, a.Anime, u.Progress, newProgress))
err = UpdateUserAnimeProgress(a.Anime, u.MalID, newProgress, updated) err = UpdateUserAnimeProgress(a.Anime, u.MalID, newProgress, updated)
if err != nil { if err != nil {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
} }
} }
} }
@@ -71,18 +78,21 @@ func LangeArbeit() {
// check if no users registered // check if no users registered
if err != nutsdb.ErrBucketEmpty { if err != nutsdb.ErrBucketEmpty {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
} }
} else { } else {
for _, u := range regUsers { for _, u := range regUsers {
_, _, err = GetUserData(u.Username) _, _, err = GetUserData(u.Username)
if err != nil { if err != nil {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
continue continue
} }
count++ count++
} }
} }
color.Infof("%d User aktualisiert\n", count) color.Infof("%d User aktualisiert\n", count)
logOut.WriteLine(fmt.Sprintf("%d User aktualisiert", count))
count = 0 count = 0
// refresh anime cache with watched // refresh anime cache with watched
@@ -90,6 +100,7 @@ func LangeArbeit() {
if err != nil { if err != nil {
if err != nutsdb.ErrBucketEmpty { if err != nutsdb.ErrBucketEmpty {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
} }
} else { } else {
for _, a := range animesUsers { for _, a := range animesUsers {
@@ -101,6 +112,7 @@ func LangeArbeit() {
err = refreshAnime(a.Anime) err = refreshAnime(a.Anime)
if err != nil { if err != nil {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
continue continue
} }
count++ count++
@@ -108,6 +120,7 @@ func LangeArbeit() {
} }
color.Infof("%d Anime aktualisiert\n", count) color.Infof("%d Anime aktualisiert\n", count)
logOut.WriteLine(fmt.Sprintf("%d Anime aktualisiert", count))
} }
func SehrLangeArbeiten() { func SehrLangeArbeiten() {
@@ -115,6 +128,7 @@ func SehrLangeArbeiten() {
err := DbClean() err := DbClean()
if err != nil { if err != nil {
color.Errorln(err.Error()) color.Errorln(err.Error())
logOut.WriteLine(err.Error())
} }
} }
} }

101
ring.go Normal file
View File

@@ -0,0 +1,101 @@
package main
import (
"fmt"
"sync"
"time"
)
// RingBuf implements an indefinitely writable circular buffer with a fixed size. Old data is overridden if write circle loops. Somewhat threadsafe.
type RingBuf struct {
sync.RWMutex
data []byte
writePos int
written int
loop bool
}
// NewRingBuf initializes a new RingBuf with a fixed size > 0
func NewRingBuf(size int) *RingBuf {
if size <= 0 {
return nil
}
rb := &RingBuf{
data: make([]byte, size),
writePos: 0,
written: 0,
loop: false,
}
return rb
}
func (rb *RingBuf) WriteLine(in string) (int, error) {
return rb.Write([]byte(fmt.Sprintf("[%s]: %s\n", time.Now().Format("2006-01-02 15:04:05"), in)))
}
// Write writes all data from input buf to RingBuf, overriding looped data
func (rb *RingBuf) Write(buf []byte) (int, error) {
rb.Lock()
defer rb.Unlock()
inLen := len(buf)
bufLen := len(rb.data)
if !rb.loop && rb.written < bufLen {
rb.written = rb.written + inLen
rb.loop = rb.written >= bufLen
}
// throw away bytes which would get looped over if input bigger than data
if inLen > bufLen {
buf = buf[inLen-bufLen:]
}
// Copy to data field
bytesToEnd := bufLen - rb.writePos
copy(rb.data[rb.writePos:], buf)
if len(buf) > bytesToEnd {
copy(rb.data, buf[bytesToEnd:])
}
// Move writePos
rb.writePos = ((rb.writePos + len(buf)) % bufLen)
return inLen, nil
}
// Size returns the maximum size of the RingBuf
func (rb *RingBuf) Size() int {
return len(rb.data)
}
// Bytes returns content of RingBuf. DON'T WRITE TO SLICE!
func (rb *RingBuf) Bytes() []byte {
rb.RLock()
defer rb.RUnlock()
bufLen := len(rb.data)
if rb.loop {
out := make([]byte, bufLen)
if rb.writePos == 0 {
copy(out, rb.data)
} else {
copy(out, rb.data[rb.writePos:])
copy(out[bufLen-rb.writePos:], rb.data[:rb.writePos])
}
return out
}
out := make([]byte, rb.writePos+1)
copy(out, rb.data[:rb.writePos])
return out
}
// Restart restarts RingBuf from 0
func (rb *RingBuf) Restart() {
rb.writePos = 0
rb.written = 0
rb.loop = false
}
// String returns content of RingBuf as string
func (rb *RingBuf) String() string {
return string(rb.Bytes())
}

View File

@@ -1,5 +1,5 @@
{% package main %} {% package main %}
{% func Index(animes []Anime) %} {% func Index(animes []Anime, log string) %}
{% collapsespace %} {% collapsespace %}
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
@@ -36,6 +36,10 @@ body { background-color: #1a1a1a; color: #fff; }
</tr> </tr>
{% endfor %} {% endfor %}
</table> </table>
<h2>Log</h2>
<pre>
{%s log %}
</pre>
</body> </body>
</html> </html>
{% endcollapsespace %} {% endcollapsespace %}

View File

@@ -18,7 +18,7 @@ var (
) )
//line season.qtpl:2 //line season.qtpl:2
func StreamIndex(qw422016 *qt422016.Writer, animes []Anime) { func StreamIndex(qw422016 *qt422016.Writer, animes []Anime, log string) {
//line season.qtpl:2 //line season.qtpl:2
qw422016.N().S(` qw422016.N().S(`
`) `)
@@ -47,35 +47,39 @@ func StreamIndex(qw422016 *qt422016.Writer, animes []Anime) {
//line season.qtpl:37 //line season.qtpl:37
} }
//line season.qtpl:37 //line season.qtpl:37
qw422016.N().S(` </table> </body> </html> `) qw422016.N().S(` </table> <h2>Log</h2> <pre> `)
//line season.qtpl:41 //line season.qtpl:41
qw422016.E().S(log)
//line season.qtpl:41
qw422016.N().S(` </pre> </body> </html> `)
//line season.qtpl:45
qw422016.N().S(` qw422016.N().S(`
`) `)
//line season.qtpl:42 //line season.qtpl:46
} }
//line season.qtpl:42 //line season.qtpl:46
func WriteIndex(qq422016 qtio422016.Writer, animes []Anime) { func WriteIndex(qq422016 qtio422016.Writer, animes []Anime, log string) {
//line season.qtpl:42 //line season.qtpl:46
qw422016 := qt422016.AcquireWriter(qq422016) qw422016 := qt422016.AcquireWriter(qq422016)
//line season.qtpl:42 //line season.qtpl:46
StreamIndex(qw422016, animes) StreamIndex(qw422016, animes, log)
//line season.qtpl:42 //line season.qtpl:46
qt422016.ReleaseWriter(qw422016) qt422016.ReleaseWriter(qw422016)
//line season.qtpl:42 //line season.qtpl:46
} }
//line season.qtpl:42 //line season.qtpl:46
func Index(animes []Anime) string { func Index(animes []Anime, log string) string {
//line season.qtpl:42 //line season.qtpl:46
qb422016 := qt422016.AcquireByteBuffer() qb422016 := qt422016.AcquireByteBuffer()
//line season.qtpl:42 //line season.qtpl:46
WriteIndex(qb422016, animes) WriteIndex(qb422016, animes, log)
//line season.qtpl:42 //line season.qtpl:46
qs422016 := string(qb422016.B) qs422016 := string(qb422016.B)
//line season.qtpl:42 //line season.qtpl:46
qt422016.ReleaseByteBuffer(qb422016) qt422016.ReleaseByteBuffer(qb422016)
//line season.qtpl:42 //line season.qtpl:46
return qs422016 return qs422016
//line season.qtpl:42 //line season.qtpl:46
} }