@@ -7,9 +7,15 @@ package main
77import (
88 "context"
99 "encoding/json"
10+ "fmt"
1011 "html/template"
12+ "io/ioutil"
1113 "log"
1214 "net/http"
15+ "os"
16+ "time"
17+
18+ "gopkg.in/yaml.v3"
1319)
1420
1521type visit struct {
@@ -18,7 +24,8 @@ type visit struct {
1824}
1925
2026type server struct {
21- db * store // *store
27+ db * store
28+ cache * lru
2229 visitCh chan visit
2330}
2431
@@ -37,6 +44,7 @@ func newServer(ctx context.Context) *server {
3744 }
3845 s := & server {
3946 db : db ,
47+ cache : newLRU (true ),
4048 visitCh : make (chan visit , 100 ),
4149 }
4250 go s .counting (ctx )
@@ -69,8 +77,59 @@ func (s *server) registerHandler() {
6977 http .Handle (conf .X .Prefix , s .xHandler (conf .X .VCS , conf .X .ImportPath , conf .X .RepoPath ))
7078}
7179
72- // backup tries to backup the data store to local files every week.
73- // it will keeps the latest 10 backups of the data read from data store.
80+ // backup tries to backup the data store to local files.
7481func (s * server ) backup (ctx context.Context ) {
75- // TODO: do self-backups
82+ if _ , err := os .Stat (conf .BackupDir ); os .IsNotExist (err ) {
83+ err := os .Mkdir (conf .BackupDir , os .ModePerm )
84+ if err != nil {
85+ log .Fatalf ("cannot create backup directory, err: %v\n " , err )
86+ }
87+ }
88+
89+ t := time .NewTicker (time .Minute * time .Duration (conf .BackupMin ))
90+ log .Printf ("internal backup is running..." )
91+ for {
92+ select {
93+ case <- t .C :
94+ r , err := s .db .Keys (ctx , "*" )
95+ if err != nil {
96+ log .Printf ("backup failure, err: %v\n " , err )
97+ continue
98+ }
99+ if len (r ) == 0 { // no keys for backup
100+ continue
101+ }
102+
103+ d := make (map [string ]interface {}, len (r ))
104+ for _ , k := range r {
105+ v , err := s .db .Fetch (ctx , k )
106+ if err != nil {
107+ log .Printf ("backup failed because of key %v, err: %v\n " , k , err )
108+ continue
109+ }
110+ var vv interface {}
111+ err = json .Unmarshal (StringToBytes (v ), & vv )
112+ if err != nil {
113+ log .Printf ("backup failed because unmarshal of key %v, err: %v\n " , k , err )
114+ continue
115+ }
116+ d [k ] = vv
117+ }
118+
119+ b , err := yaml .Marshal (d )
120+ if err != nil {
121+ log .Printf ("backup failed when converting to yaml, err: %v\n " , err )
122+ continue
123+ }
124+
125+ name := fmt .Sprintf ("/backup-%s.yml" , time .Now ().Format (time .RFC3339 ))
126+ err = ioutil .WriteFile (conf .BackupDir + name , b , os .ModePerm )
127+ if err != nil {
128+ log .Printf ("backup failed when saving the file, err: %v\n " , err )
129+ continue
130+ }
131+ case <- ctx .Done ():
132+ return
133+ }
134+ }
76135}
0 commit comments