forked from kiwiirc/plugin-fileuploader
/
uploadserver.go
118 lines (96 loc) · 3.01 KB
/
uploadserver.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package server
import (
"net/http"
"sync"
"github.com/gin-gonic/gin"
"github.com/kiwiirc/plugin-fileuploader/db"
"github.com/kiwiirc/plugin-fileuploader/events"
"github.com/kiwiirc/plugin-fileuploader/expirer"
"github.com/kiwiirc/plugin-fileuploader/logging"
"github.com/kiwiirc/plugin-fileuploader/shardedfilestore"
"github.com/rs/zerolog"
)
// UploadServer is a simple configurable service for file sharing.
// Compatible with TUS upload clients.
type UploadServer struct {
DBConn *db.DatabaseConnection
Router *gin.Engine
cfg Config
log *zerolog.Logger
store *shardedfilestore.ShardedFileStore
expirer *expirer.Expirer
httpServer *http.Server
startedMu sync.Mutex
started chan struct{}
tusEventBroadcaster *events.TusEventBroadcaster
}
// GetStartedChan returns a channel that will close when the server startup is complete
func (serv *UploadServer) GetStartedChan() chan struct{} {
serv.startedMu.Lock()
defer serv.startedMu.Unlock()
if serv.started == nil {
serv.started = make(chan struct{})
}
return serv.started
}
func init() {
gin.SetMode(gin.ReleaseMode)
}
// Run starts the UploadServer
func (serv *UploadServer) Run(replaceableHandler *ReplaceableHandler) error {
serv.Router = gin.New()
serv.Router.Use(logging.GinLogger(serv.log), gin.Recovery())
serv.DBConn = db.ConnectToDB(serv.log, db.DBConfig{
DriverName: serv.cfg.Database.Type,
DSN: serv.cfg.Database.Path,
})
serv.store = shardedfilestore.New(
serv.cfg.Storage.Path,
serv.cfg.Storage.ShardLayers,
serv.DBConn,
serv.log,
)
serv.expirer = expirer.New(
serv.store,
serv.cfg.Expiration.MaxAge.Duration,
serv.cfg.Expiration.IdentifiedMaxAge.Duration,
serv.cfg.Expiration.CheckInterval.Duration,
serv.cfg.JwtSecretsByIssuer,
serv.log,
)
err := serv.registerTusHandlers(serv.Router, serv.store)
if err != nil {
return err
}
// closed channel indicates that startup is complete
close(serv.GetStartedChan())
if replaceableHandler != nil {
// set ReplaceableHandler that's mounted in an external server
replaceableHandler.Handler = serv.Router
return nil
}
// otherwise run our own http server
serv.httpServer = &http.Server{
Addr: serv.cfg.Server.ListenAddress,
Handler: serv.Router,
}
return serv.httpServer.ListenAndServe()
}
// Shutdown gracefully terminates the UploadServer instance.
// The HTTP listen socket will close immediately, causing the .Run() call to return.
// The call to .Shutdown() will block until all outstanding requests have been served and
// other resources like database connections and timers have been closed and stopped.
func (serv *UploadServer) Shutdown() {
// wait for startup to complete
<-serv.GetStartedChan()
// wait for all requests to finish
if serv.httpServer != nil {
serv.httpServer.Shutdown(nil)
}
// stop running FileStore GC cycles
serv.expirer.Stop()
// close db connections
serv.DBConn.DB.Close()
// close event broadcaster
serv.tusEventBroadcaster.Close()
}