11package openlistlib
22
33import (
4- "context"
54 "errors"
6- "fmt"
7- "net"
8- "net/http"
9- "os"
10- "strconv"
115 "time"
126
13- "github.com/OpenListTeam/OpenList/v4/openlistlib/internal"
14- "github.com/OpenListTeam/OpenList/v4/cmd"
15- "github.com/OpenListTeam/OpenList/v4/cmd/flags"
167 "github.com/OpenListTeam/OpenList/v4/internal/bootstrap"
17- "github.com/OpenListTeam/OpenList/v4/internal/conf"
188 "github.com/OpenListTeam/OpenList/v4/internal/db"
9+ "github.com/OpenListTeam/OpenList/v4/openlistlib/internal"
1910 "github.com/OpenListTeam/OpenList/v4/pkg/utils"
20- "github.com/OpenListTeam/OpenList/v4/server"
21- "github.com/OpenListTeam/sftpd-openlist"
22- ftpserver "github.com/fclairamb/ftpserverlib"
23- "github.com/gin-gonic/gin"
2411 log "github.com/sirupsen/logrus"
2512)
2613
@@ -34,12 +21,22 @@ type Event interface {
3421 OnProcessExit (code int )
3522}
3623
37- var event Event
24+ var startFailedHookUuid = ""
25+ var shutdownHookUuid = ""
3826var logFormatter * internal.MyFormatter
3927
40- func Init (e Event , cb LogCallback ) error {
41- event = e
42- cmd .Init ()
28+ func Init (event Event , cb LogCallback ) error {
29+ if startFailedHookUuid != "" {
30+ bootstrap .RemoveEndpointStartFailedHook (startFailedHookUuid )
31+ startFailedHookUuid = ""
32+ }
33+ if shutdownHookUuid != "" {
34+ bootstrap .RemoveEndpointShutdownHook (shutdownHookUuid )
35+ shutdownHookUuid = ""
36+ }
37+ bootstrap .Init ()
38+ startFailedHookUuid = bootstrap .RegisterEndpointStartFailedHook (event .OnStartError )
39+ shutdownHookUuid = bootstrap .RegisterEndpointShutdownHook (event .OnShutdown )
4340 logFormatter = & internal.MyFormatter {
4441 OnLog : func (entry * log.Entry ) {
4542 cb .OnLog (int16 (entry .Level ), entry .Time .UnixMilli (), entry .Message )
@@ -54,206 +51,30 @@ func Init(e Event, cb LogCallback) error {
5451 return nil
5552}
5653
57- var httpSrv , httpsSrv , unixSrv * http.Server
58-
59- func listenAndServe (t string , srv * http.Server ) {
60- err := srv .ListenAndServe ()
61- if err != nil && err != http .ErrServerClosed {
62- event .OnStartError (t , err .Error ())
63- } else {
64- event .OnShutdown (t )
65- }
66- }
67-
6854func IsRunning (t string ) bool {
69- switch t {
70- case "http" :
71- return httpSrv != nil
72- case "https" :
73- return httpsSrv != nil
74- case "unix" :
75- return unixSrv != nil
76- }
77-
78- return httpSrv != nil && httpsSrv != nil && unixSrv != nil
55+ return bootstrap .IsRunning (t )
7956}
8057
8158// Start starts the server
8259func Start () {
83- if conf .Conf .DelayedStart != 0 {
84- utils .Log .Infof ("delayed start for %d seconds" , conf .Conf .DelayedStart )
85- time .Sleep (time .Duration (conf .Conf .DelayedStart ) * time .Second )
86- }
87- bootstrap .InitOfflineDownloadTools ()
88- bootstrap .LoadStorages ()
89- bootstrap .InitTaskManager ()
90- if ! flags .Debug && ! flags .Dev {
91- gin .SetMode (gin .ReleaseMode )
92- }
93- r := gin .New ()
94- r .Use (gin .LoggerWithWriter (log .StandardLogger ().Out ), gin .RecoveryWithWriter (log .StandardLogger ().Out ))
95- server .Init (r )
96-
97- if conf .Conf .Scheme .HttpPort != - 1 {
98- httpBase := fmt .Sprintf ("%s:%d" , conf .Conf .Scheme .Address , conf .Conf .Scheme .HttpPort )
99- utils .Log .Infof ("start HTTP server @ %s" , httpBase )
100- httpSrv = & http.Server {Addr : httpBase , Handler : r }
101- go func () {
102- listenAndServe ("http" , httpSrv )
103- httpSrv = nil
104- }()
105- }
106- if conf .Conf .Scheme .HttpsPort != - 1 {
107- httpsBase := fmt .Sprintf ("%s:%d" , conf .Conf .Scheme .Address , conf .Conf .Scheme .HttpsPort )
108- utils .Log .Infof ("start HTTPS server @ %s" , httpsBase )
109- httpsSrv = & http.Server {Addr : httpsBase , Handler : r }
110- go func () {
111- listenAndServe ("https" , httpsSrv )
112- httpsSrv = nil
113- }()
114- }
115- if conf .Conf .Scheme .UnixFile != "" {
116- utils .Log .Infof ("start unix server @ %s" , conf .Conf .Scheme .UnixFile )
117- unixSrv = & http.Server {Handler : r }
118- go func () {
119- listener , err := net .Listen ("unix" , conf .Conf .Scheme .UnixFile )
120- if err != nil {
121- //utils.Log.Fatalf("failed to listenAndServe unix: %+v", err)
122- event .OnStartError ("unix" , err .Error ())
123- } else {
124- // set socket file permission
125- mode , err := strconv .ParseUint (conf .Conf .Scheme .UnixFilePerm , 8 , 32 )
126- if err != nil {
127- utils .Log .Errorf ("failed to parse socket file permission: %+v" , err )
128- } else {
129- err = os .Chmod (conf .Conf .Scheme .UnixFile , os .FileMode (mode ))
130- if err != nil {
131- utils .Log .Errorf ("failed to chmod socket file: %+v" , err )
132- }
133- }
134- err = unixSrv .Serve (listener )
135- if err != nil && err != http .ErrServerClosed {
136- event .OnStartError ("unix" , err .Error ())
137- }
138- }
139-
140- unixSrv = nil
141- }()
142- }
143- if conf .Conf .S3 .Port != - 1 && conf .Conf .S3 .Enable {
144- s3r := gin .New ()
145- s3r .Use (gin .LoggerWithWriter (log .StandardLogger ().Out ), gin .RecoveryWithWriter (log .StandardLogger ().Out ))
146- server .InitS3 (s3r )
147- s3Base := fmt .Sprintf ("%s:%d" , conf .Conf .Scheme .Address , conf .Conf .S3 .Port )
148- fmt .Printf ("start S3 server @ %s\n " , s3Base )
149- utils .Log .Infof ("start S3 server @ %s" , s3Base )
150- go func () {
151- var err error
152- if conf .Conf .S3 .SSL {
153- httpsSrv = & http.Server {Addr : s3Base , Handler : s3r }
154- err = httpsSrv .ListenAndServeTLS (conf .Conf .Scheme .CertFile , conf .Conf .Scheme .KeyFile )
155- }
156- if ! conf .Conf .S3 .SSL {
157- httpSrv = & http.Server {Addr : s3Base , Handler : s3r }
158- err = httpSrv .ListenAndServe ()
159- }
160- if err != nil && ! errors .Is (err , http .ErrServerClosed ) {
161- utils .Log .Fatalf ("failed to start s3 server: %s" , err .Error ())
162- }
163- }()
164- }
165- var ftpDriver * server.FtpMainDriver
166- var ftpServer * ftpserver.FtpServer
167- if conf .Conf .FTP .Listen != "" && conf .Conf .FTP .Enable {
168- var err error
169- ftpDriver , err = server .NewMainDriver ()
170- if err != nil {
171- utils .Log .Fatalf ("failed to start ftp driver: %s" , err .Error ())
172- } else {
173- fmt .Printf ("start ftp server on %s\n " , conf .Conf .FTP .Listen )
174- utils .Log .Infof ("start ftp server on %s" , conf .Conf .FTP .Listen )
175- go func () {
176- ftpServer = ftpserver .NewFtpServer (ftpDriver )
177- err = ftpServer .ListenAndServe ()
178- if err != nil {
179- utils .Log .Fatalf ("problem ftp server listening: %s" , err .Error ())
180- }
181- }()
182- }
183- }
184- var sftpDriver * server.SftpDriver
185- var sftpServer * sftpd.SftpServer
186- if conf .Conf .SFTP .Listen != "" && conf .Conf .SFTP .Enable {
187- var err error
188- sftpDriver , err = server .NewSftpDriver ()
189- if err != nil {
190- utils .Log .Fatalf ("failed to start sftp driver: %s" , err .Error ())
191- } else {
192- fmt .Printf ("start sftp server on %s" , conf .Conf .SFTP .Listen )
193- utils .Log .Infof ("start sftp server on %s" , conf .Conf .SFTP .Listen )
194- go func () {
195- sftpServer = sftpd .NewSftpServer (sftpDriver )
196- err = sftpServer .RunServer ()
197- if err != nil {
198- utils .Log .Fatalf ("problem sftp server listening: %s" , err .Error ())
199- }
200- }()
201- }
202- }
203- }
204-
205- func shutdown (srv * http.Server , timeout time.Duration ) error {
206- if srv == nil {
207- return nil
208- }
209-
210- ctx , cancel := context .WithTimeout (context .Background (), timeout )
211- defer cancel ()
212-
213- err := srv .Shutdown (ctx )
214-
215- return err
60+ bootstrap .Start ()
21661}
21762
21863// Shutdown timeout 毫秒
21964func Shutdown (timeout int64 ) (err error ) {
22065 timeoutDuration := time .Duration (timeout ) * time .Millisecond
221- utils .Log .Println ("Shutdown server..." )
222- if conf .Conf .Scheme .HttpPort != - 1 {
223- err := shutdown (httpSrv , timeoutDuration )
224- if err != nil {
225- return err
226- }
227- httpSrv = nil
228- utils .Log .Println ("Server HTTP Shutdown" )
229- }
230- if conf .Conf .Scheme .HttpsPort != - 1 {
231- err := shutdown (httpsSrv , timeoutDuration )
232- if err != nil {
233- return err
234- }
235- httpsSrv = nil
236- utils .Log .Println ("Server HTTPS Shutdown" )
237- }
238- if conf .Conf .Scheme .UnixFile != "" {
239- err := shutdown (unixSrv , timeoutDuration )
240- if err != nil {
241- return err
242- }
243- unixSrv = nil
244- utils .Log .Println ("Server UNIX Shutdown" )
245- }
66+ bootstrap .Shutdown (timeoutDuration )
24667
24768 // Force database sync before shutdown
24869 ForceDBSync ()
249- //cmd .Release()
70+ //bootstrap .Release()
25071 return nil
25172}
25273
25374// ForceDBSync forces SQLite WAL checkpoint to sync data to main database file
25475func ForceDBSync () error {
25576 log .Info ("Forcing database sync (WAL checkpoint)..." )
256-
77+
25778 // Get the database instance and execute WAL checkpoint
25879 gormDB := db .GetDb ()
25980 if gormDB != nil {
@@ -262,24 +83,24 @@ func ForceDBSync() error {
26283 log .Errorf ("Failed to get database connection: %v" , err )
26384 return err
26485 }
265-
86+
26687 // Execute WAL checkpoint with TRUNCATE mode to force sync and remove WAL files
26788 _ , err = sqlDB .Exec ("PRAGMA wal_checkpoint(TRUNCATE)" )
26889 if err != nil {
26990 log .Errorf ("Failed to execute WAL checkpoint: %v" , err )
27091 return err
27192 }
272-
93+
27394 // Also execute synchronous commit to ensure data is written to disk
27495 _ , err = sqlDB .Exec ("PRAGMA synchronous=FULL" )
27596 if err != nil {
27697 log .Warnf ("Failed to set synchronous mode: %v" , err )
27798 }
278-
99+
279100 log .Info ("Database sync completed successfully" )
280101 } else {
281102 log .Warn ("Database instance is nil, skipping sync" )
282103 }
283-
104+
284105 return nil
285106}
0 commit comments