11package services
22
33import (
4- "io/ioutil "
4+ "io"
55 "os"
66 "path/filepath"
77 "sync"
@@ -26,8 +26,9 @@ type Persistence interface {
2626 StoreSessions (types.Sessions )
2727}
2828
29+ var mu sync.Mutex
30+
2931type persistence struct {
30- mu sync.Mutex
3132 persistenceDirectory string
3233}
3334
@@ -39,8 +40,8 @@ func NewPersistence(persistenceDirectory string) Persistence {
3940}
4041
4142func (p * persistence ) StoreMocks (sessionID string , mocks types.Mocks ) {
42- p . mu .Lock ()
43- defer p . mu .Unlock ()
43+ mu .Lock ()
44+ defer mu .Unlock ()
4445 if p .persistenceDirectory == "" {
4546 return
4647 }
@@ -56,8 +57,8 @@ func (p *persistence) StoreMocks(sessionID string, mocks types.Mocks) {
5657}
5758
5859func (p * persistence ) StoreHistory (sessionID string , history types.History ) {
59- p . mu .Lock ()
60- defer p . mu .Unlock ()
60+ mu .Lock ()
61+ defer mu .Unlock ()
6162 if p .persistenceDirectory == "" {
6263 return
6364 }
@@ -73,8 +74,8 @@ func (p *persistence) StoreHistory(sessionID string, history types.History) {
7374}
7475
7576func (p * persistence ) StoreSession (summary []types.SessionSummary , session * types.Session ) {
76- p . mu .Lock ()
77- defer p . mu .Unlock ()
77+ mu .Lock ()
78+ defer mu .Unlock ()
7879 if p .persistenceDirectory == "" {
7980 return
8081 }
@@ -99,18 +100,14 @@ func (p *persistence) StoreSession(summary []types.SessionSummary, session *type
99100}
100101
101102func (p * persistence ) StoreSessions (sessions types.Sessions ) {
102- p . mu .Lock ()
103- defer p . mu .Unlock ()
103+ mu .Lock ()
104+ defer mu .Unlock ()
104105 if p .persistenceDirectory == "" {
105106 return
106107 }
107- if err := p .cleanAll (); err != nil {
108- log .Error ("unable to clean directory: " , err )
109- return
110- }
111108 var sessionsGroup errgroup.Group
112- for _ , session := range sessions {
113- session := session
109+ for _ , ses := range sessions {
110+ session := * ses
114111 sessionsGroup .Go (func () error {
115112 if err := p .createSessionDirectory (session .ID ); err != nil {
116113 return err
@@ -134,11 +131,14 @@ func (p *persistence) StoreSessions(sessions types.Sessions) {
134131 if err := sessionsGroup .Wait (); err != nil {
135132 log .Error ("unable to store sessions: " , err )
136133 }
134+ if err := p .cleanOutdatedSessions (sessions ); err != nil {
135+ log .Error ("unable to clean outdated sessions: " , err )
136+ }
137137}
138138
139139func (p * persistence ) LoadSessions () (types.Sessions , error ) {
140- p . mu .Lock ()
141- defer p . mu .Unlock ()
140+ mu .Lock ()
141+ defer mu .Unlock ()
142142 if p .persistenceDirectory == "" {
143143 return nil , nil
144144 }
@@ -147,10 +147,13 @@ func (p *persistence) LoadSessions() (types.Sessions, error) {
147147 }
148148 file , err := os .Open (filepath .Join (p .persistenceDirectory , sessionsFileName ))
149149 if err != nil {
150+ if err == os .ErrNotExist {
151+ return types.Sessions {}, nil
152+ }
150153 return nil , err
151154 }
152155 defer file .Close ()
153- bytes , err := ioutil .ReadAll (file )
156+ bytes , err := io .ReadAll (file )
154157 if err != nil {
155158 return nil , err
156159 }
@@ -161,15 +164,16 @@ func (p *persistence) LoadSessions() (types.Sessions, error) {
161164 }
162165 var sessionsGroup errgroup.Group
163166 var sessionsLock sync.Mutex
164- for _ , session := range sessions {
165- session := session
167+ for _ , ses := range sessions {
168+ session := * ses
166169 sessionsGroup .Go (func () error {
167170 historyFile , err := os .Open (filepath .Join (p .persistenceDirectory , session .ID , historyFileName ))
168171 if err != nil {
172+ log .WithError (err ).Errorf ("Unable to open history file for session %q" , session .ID )
169173 return err
170174 }
171175 defer historyFile .Close ()
172- bytes , err := ioutil .ReadAll (historyFile )
176+ bytes , err := io .ReadAll (historyFile )
173177 if err != nil {
174178 return err
175179 }
@@ -186,10 +190,11 @@ func (p *persistence) LoadSessions() (types.Sessions, error) {
186190 sessionsGroup .Go (func () error {
187191 mocksFile , err := os .Open (filepath .Join (p .persistenceDirectory , session .ID , mocksFileName ))
188192 if err != nil {
193+ log .WithError (err ).Errorf ("Unable to open mocks file for session %q" , session .ID )
189194 return err
190195 }
191196 defer mocksFile .Close ()
192- bytes , err := ioutil .ReadAll (mocksFile )
197+ bytes , err := io .ReadAll (mocksFile )
193198 if err != nil {
194199 return err
195200 }
@@ -213,10 +218,15 @@ func (p *persistence) LoadSessions() (types.Sessions, error) {
213218 if err := sessionsGroup .Wait (); err != nil {
214219 return nil , err
215220 }
221+ if err := p .cleanOutdatedSessions (sessions ); err != nil {
222+ return nil , err
223+ }
224+
216225 return sessions , nil
217226}
218227
219228func (p * persistence ) createSessionDirectory (sessionID string ) error {
229+ log .Debugf ("Create directory for session %q" , sessionID )
220230 sessionDirectory := filepath .Join (p .persistenceDirectory , sessionID )
221231 if err := os .MkdirAll (sessionDirectory , os .ModePerm ); err != nil && ! os .IsExist (err ) {
222232 return err
@@ -225,18 +235,20 @@ func (p *persistence) createSessionDirectory(sessionID string) error {
225235}
226236
227237func (p * persistence ) persistHistory (sessionID string , h types.History ) error {
238+ log .Debugf ("Persist history for session %q" , sessionID )
228239 history , err := yaml .Marshal (h )
229240 if err != nil {
230241 return err
231242 }
232- err = ioutil .WriteFile (filepath .Join (p .persistenceDirectory , sessionID , historyFileName ), history , os .ModePerm )
243+ err = os .WriteFile (filepath .Join (p .persistenceDirectory , sessionID , historyFileName ), history , os .ModePerm )
233244 if err != nil {
234245 return err
235246 }
236247 return nil
237248}
238249
239250func (p * persistence ) persistMocks (sessionID string , m types.Mocks ) error {
251+ log .Debugf ("Persist mocks for session %q" , sessionID )
240252 // we need to reverse mocks before storage in order to have a reusable mocks file as mocks are stored as a stack
241253 orderedMocks := make (types.Mocks , 0 , len (m ))
242254 for i := len (m ) - 1 ; i >= 0 ; i -- {
@@ -246,35 +258,43 @@ func (p *persistence) persistMocks(sessionID string, m types.Mocks) error {
246258 if err != nil {
247259 return err
248260 }
249- err = ioutil .WriteFile (filepath .Join (p .persistenceDirectory , sessionID , mocksFileName ), mocks , os .ModePerm )
261+ err = os .WriteFile (filepath .Join (p .persistenceDirectory , sessionID , mocksFileName ), mocks , os .ModePerm )
250262 if err != nil {
251263 return err
252264 }
253265 return nil
254266}
255267
256268func (p * persistence ) persistSessionsSummary (summary []types.SessionSummary ) error {
269+ log .Debug ("Persist sessions summary" )
257270 sessions , err := yaml .Marshal (summary )
258271 if err != nil {
259272 return err
260273 }
261- err = ioutil .WriteFile (filepath .Join (p .persistenceDirectory , sessionsFileName ), sessions , os .ModePerm )
274+ err = os .WriteFile (filepath .Join (p .persistenceDirectory , sessionsFileName ), sessions , os .ModePerm )
262275 if err != nil {
263276 return err
264277 }
265278 return nil
266279}
267280
268- func (p * persistence ) cleanAll () error {
269- if err := os .MkdirAll (p .persistenceDirectory , os .ModePerm ); err != nil && ! os .IsExist (err ) {
270- return err
271- }
272- files , err := ioutil .ReadDir (p .persistenceDirectory )
281+ func (p * persistence ) cleanOutdatedSessions (sessions types.Sessions ) error {
282+ sessionsIDs := make (map [string ]bool , len (sessions ))
283+ for _ , ses := range sessions {
284+ session := * ses
285+ sessionsIDs [session .ID ] = true
286+ }
287+ log .Debug ("Clean old sessions" )
288+ entries , err := os .ReadDir (p .persistenceDirectory )
273289 if err != nil {
274290 return err
275291 }
276- for _ , file := range files {
277- os .RemoveAll (filepath .Join (p .persistenceDirectory , file .Name ()))
292+ for _ , entry := range entries {
293+ if entry .IsDir () && ! sessionsIDs [entry .Name ()] {
294+ path := filepath .Join (p .persistenceDirectory , entry .Name ())
295+ log .Debugf ("Removing directory: %q" , path )
296+ os .RemoveAll (path )
297+ }
278298 }
279299 return nil
280300}
0 commit comments