@@ -3,6 +3,7 @@ package processor
33import (
44 "database/sql"
55 "errors"
6+ "fmt"
67 "time"
78
89 "github.com/cloudbox/autoscan"
@@ -12,18 +13,15 @@ import (
1213)
1314
1415type datastore struct {
15- db * sql.DB
16+ * sql.DB
1617}
1718
1819const sqlSchema = `
1920CREATE TABLE IF NOT EXISTS scan (
2021 "folder" TEXT NOT NULL,
21- "file" TEXT NOT NULL,
2222 "priority" INTEGER NOT NULL,
2323 "time" DATETIME NOT NULL,
24- "retries" INTEGER NOT NULL,
25- "removed" BOOLEAN NOT NULL,
26- PRIMARY KEY(folder, file)
24+ PRIMARY KEY(folder)
2725)
2826`
2927
@@ -38,30 +36,26 @@ func newDatastore(path string) (*datastore, error) {
3836 return nil , err
3937 }
4038
41- store := & datastore {
42- db : db ,
43- }
39+ store := & datastore {db }
4440
4541 return store , nil
4642}
4743
4844const sqlUpsert = `
49- INSERT INTO scan (folder, file, priority, time, retries, removed )
50- VALUES (?, ?, ?, ?, ?, ? )
51- ON CONFLICT (folder, file ) DO UPDATE SET
45+ INSERT INTO scan (folder, priority, time)
46+ VALUES (?, ?, ?)
47+ ON CONFLICT (folder) DO UPDATE SET
5248 priority = MAX(excluded.priority, scan.priority),
53- time = excluded.time,
54- retries = excluded.retries,
55- removed = min(excluded.removed, scan.removed)
49+ time = excluded.time
5650`
5751
58- func (store datastore ) upsert (tx * sql.Tx , scan autoscan.Scan ) error {
59- _ , err := tx .Exec (sqlUpsert , scan .Folder , scan .File , scan . Priority , scan .Time , scan . Retries , scan . Removed )
52+ func (store * datastore ) upsert (tx * sql.Tx , scan autoscan.Scan ) error {
53+ _ , err := tx .Exec (sqlUpsert , scan .Folder , scan .Priority , scan .Time )
6054 return err
6155}
6256
63- func (store datastore ) Upsert (scans []autoscan.Scan ) error {
64- tx , err := store .db . Begin ()
57+ func (store * datastore ) Upsert (scans []autoscan.Scan ) error {
58+ tx , err := store .Begin ()
6559 if err != nil {
6660 return err
6761 }
@@ -79,111 +73,42 @@ func (store datastore) Upsert(scans []autoscan.Scan) error {
7973 return tx .Commit ()
8074}
8175
82- const sqlGetMatching = `
83- SELECT folder, file, priority, retries, removed, time FROM scan
84- WHERE folder = (
85- SELECT folder
86- FROM scan
87- GROUP BY folder
88- HAVING MAX(time) < ?
89- ORDER BY priority DESC, time ASC
90- LIMIT 1
91- )
76+ const sqlGetAvailableScan = `
77+ SELECT folder, priority, time FROM scan
78+ WHERE time < ?
79+ ORDER BY priority DESC, time ASC
80+ LIMIT 1
9281`
9382
94- func (store datastore ) GetMatching (minAge time.Duration ) (scans []autoscan.Scan , err error ) {
95- rows , err := store .db .Query (sqlGetMatching , now ().Add (- 1 * minAge ))
96- if errors .Is (err , sql .ErrNoRows ) {
97- return scans , nil
98- }
99-
100- if err != nil {
101- return scans , err
102- }
103-
104- defer rows .Close ()
105- for rows .Next () {
106- scan := autoscan.Scan {}
107- err = rows .Scan (& scan .Folder , & scan .File , & scan .Priority , & scan .Retries , & scan .Removed , & scan .Time )
108- if err != nil {
109- return scans , err
110- }
83+ func (store * datastore ) GetAvailableScan (minAge time.Duration ) (autoscan.Scan , error ) {
84+ row := store .QueryRow (sqlGetAvailableScan , now ().Add (- 1 * minAge ))
11185
112- scans = append (scans , scan )
86+ scan := autoscan.Scan {}
87+ err := row .Scan (& scan .Folder , & scan .Priority , & scan .Time )
88+ switch {
89+ case errors .Is (err , sql .ErrNoRows ):
90+ return scan , autoscan .ErrNoScans
91+ case err != nil :
92+ return scan , fmt .Errorf ("get matching: %s: %w" , err , autoscan .ErrFatal )
11393 }
11494
115- return scans , rows .Err ()
116- }
117-
118- const sqlIncrementRetries = `
119- UPDATE scan
120- SET retries = retries + 1, time = ?
121- WHERE folder = ?
122- `
123-
124- // Increment the retry count of all the children of a folder.
125- // Furthermore, we also update the timestamp to the current time
126- // so the children will not get scanned for 5 minutes.
127- func (store datastore ) incrementRetries (tx * sql.Tx , folder string ) error {
128- _ , err := tx .Exec (sqlIncrementRetries , now (), folder )
129- return err
130- }
131-
132- const sqlDeleteRetries = `
133- DELETE FROM scan
134- WHERE folder = ? AND retries > ?
135- `
136-
137- func (store datastore ) deleteRetries (tx * sql.Tx , folder string , maxRetries int ) error {
138- _ , err := tx .Exec (sqlDeleteRetries , folder , maxRetries )
139- return err
140- }
141-
142- func (store datastore ) Retry (folder string , maxRetries int ) error {
143- tx , err := store .db .Begin ()
144- if err != nil {
145- return err
146- }
147-
148- err = store .incrementRetries (tx , folder )
149- if err != nil {
150- if rbErr := tx .Rollback (); rbErr != nil {
151- panic (rbErr )
152- }
153-
154- return err
155- }
156-
157- err = store .deleteRetries (tx , folder , maxRetries )
158- if err != nil {
159- if rbErr := tx .Rollback (); rbErr != nil {
160- panic (rbErr )
161- }
162-
163- return err
164- }
165-
166- return tx .Commit ()
95+ return scan , nil
16796}
16897
16998const sqlGetAll = `
170- SELECT folder, file, priority, retries, removed , time FROM scan
99+ SELECT folder, priority, time FROM scan
171100`
172101
173- func (store datastore ) GetAll () (scans []autoscan.Scan , err error ) {
174- rows , err := store .db .Query (sqlGetAll )
175- if errors .Is (err , sql .ErrNoRows ) {
176- return scans , nil
177- }
178-
102+ func (store * datastore ) GetAll () (scans []autoscan.Scan , err error ) {
103+ rows , err := store .Query (sqlGetAll )
179104 if err != nil {
180105 return scans , err
181106 }
182107
183108 defer rows .Close ()
184109 for rows .Next () {
185110 scan := autoscan.Scan {}
186- err = rows .Scan (& scan .Folder , & scan .File , & scan . Priority , & scan . Retries , & scan . Removed , & scan .Time )
111+ err = rows .Scan (& scan .Folder , & scan .Priority , & scan .Time )
187112 if err != nil {
188113 return scans , err
189114 }
@@ -195,32 +120,16 @@ func (store datastore) GetAll() (scans []autoscan.Scan, err error) {
195120}
196121
197122const sqlDelete = `
198- DELETE FROM scan
199- WHERE folder=? AND file=?
123+ DELETE FROM scan WHERE folder=?
200124`
201125
202- func (store datastore ) delete (tx * sql.Tx , scan autoscan.Scan ) error {
203- _ , err := tx .Exec (sqlDelete , scan .Folder , scan .File )
204- return err
205- }
206-
207- func (store datastore ) Delete (scans []autoscan.Scan ) error {
208- tx , err := store .db .Begin ()
126+ func (store * datastore ) Delete (scan autoscan.Scan ) error {
127+ _ , err := store .Exec (sqlDelete , scan .Folder )
209128 if err != nil {
210- return err
129+ return fmt . Errorf ( "delete: %s: %w" , err , autoscan . ErrFatal )
211130 }
212131
213- for _ , scan := range scans {
214- if err = store .delete (tx , scan ); err != nil {
215- if rollbackErr := tx .Rollback (); rollbackErr != nil {
216- panic (rollbackErr )
217- }
218-
219- return err
220- }
221- }
222-
223- return tx .Commit ()
132+ return nil
224133}
225134
226135var now = time .Now
0 commit comments