@@ -64,7 +64,7 @@ type Folder struct {
6464 config * FolderConfig
6565 files []string
6666 retries uint
67- archives [] string
67+ archives xtractr. ArchiveList
6868}
6969
7070type eventData struct {
@@ -239,10 +239,10 @@ func (f *Folders) Remove(folder string) {
239239}
240240
241241// extractTrackedItem starts an archive or folder's extraction after it hasn't been written to in a while.
242- func (u * Unpackerr ) extractTrackedItem (name string , folder * Folder ) {
242+ func (u * Unpackerr ) extractTrackedItem (name string , folder * Folder , now time. Time ) {
243243 u .folders .Remove (name ) // stop the fs watcher(s).
244244 // update status.
245- u .folders .Folders [name ].updated = time . Now ()
245+ u .folders .Folders [name ].updated = now
246246 u .folders .Folders [name ].status = QUEUED
247247
248248 // Do not extract r00 file if rar file with same name exists.
@@ -255,7 +255,7 @@ func (u *Unpackerr) extractTrackedItem(name string, folder *Folder) {
255255 }
256256
257257 // create a queue counter in the main history; add to u.Map and send webhook for a new folder.
258- u .updateQueueStatus (& newStatus {Name : name , Status : QUEUED }, true )
258+ u .updateQueueStatus (& newStatus {Name : name , Status : QUEUED }, u . folders . Folders [ name ]. updated , true )
259259 u .updateHistory (FolderString + ": " + name )
260260
261261 var exclude []string
@@ -320,39 +320,24 @@ func (u *Unpackerr) folderXtractrCallback(resp *xtractr.Response) {
320320 folder .status = EXTRACTEDNOTHING
321321 u .Printf ("[Folder] %s: %s: %v" , folder .status .Desc (), resp .X .Name , resp .Error )
322322 case resp .Error != nil :
323+ folder .archives = resp .Archives
323324 folder .status = EXTRACTFAILED
324325 u .Errorf ("[Folder] %s: %s: %v" , folder .status .Desc (), resp .X .Name , resp .Error )
325326 u .updateMetrics (resp , FolderString , folder .config .Path )
326-
327- for _ , v := range resp .Archives {
328- folder .archives = append (folder .archives , v ... )
329- }
330327 default : // this runs in a go routine
331- for _ , v := range resp .Archives {
332- folder .archives = append (folder .archives , v ... )
333- }
334-
335328 u .updateMetrics (resp , FolderString , folder .config .Path )
336329 u .Printf ("[Folder] Extraction Finished: %s => elapsed: %v, archives: %d, " +
337330 "extra archives: %d, files extracted: %d, written: %dMiB" ,
338- resp .X .Name , resp .Elapsed .Round (time .Second ), len ( folder . archives ),
339- mapLen ( resp .Extras ), len (resp .NewFiles ), resp .Size / mebiByte )
331+ resp .X .Name , resp .Elapsed .Round (time .Second ), resp . Archives . Count ( ),
332+ resp .Extras . Count ( ), len (resp .NewFiles ), resp .Size / mebiByte )
340333
334+ folder .archives = resp .Archives
341335 folder .status = EXTRACTED
342336 folder .files = resp .NewFiles
343337 }
344338
345- folder .updated = time .Now ()
346-
347- u .updateQueueStatus (& newStatus {Name : resp .X .Name , Resp : resp , Status : folder .status }, true )
348- }
349-
350- func mapLen (in map [string ][]string ) (out int ) {
351- for _ , v := range in {
352- out += len (v )
353- }
354-
355- return out
339+ folder .updated = resp .Started .Add (resp .Elapsed )
340+ u .updateQueueStatus (& newStatus {Name : resp .X .Name , Resp : resp , Status : folder .status }, folder .updated , true )
356341}
357342
358343// watchFSNotify reads file system events from a channel and processes them.
@@ -415,17 +400,17 @@ func (f *Folders) handleFileEvent(name, operation string) {
415400}
416401
417402// processEvent is here to process the event in the `*Unpackerr` scope before sending it back to the `*Folders` scope.
418- func (u * Unpackerr ) processEvent (event * eventData ) {
403+ func (u * Unpackerr ) processEvent (event * eventData , now time. Time ) {
419404 // Do not watch our own log file.
420405 if event .file == u .Config .LogFile || event .file == u .Config .Webserver .LogFile {
421406 return
422407 }
423408
424- u .folders .processEvent (event )
409+ u .folders .processEvent (event , now )
425410}
426411
427412// processEvent processes the event that was received.
428- func (f * Folders ) processEvent (event * eventData ) {
413+ func (f * Folders ) processEvent (event * eventData , now time. Time ) {
429414 dirPath := filepath .Join (event .cnfg .Path , event .name )
430415
431416 stat , err := os .Stat (dirPath )
@@ -447,13 +432,13 @@ func (f *Folders) processEvent(event *eventData) {
447432 return
448433 }
449434
450- f .saveEvent (event , dirPath )
435+ f .saveEvent (event , dirPath , now )
451436}
452437
453- func (f * Folders ) saveEvent (event * eventData , dirPath string ) {
438+ func (f * Folders ) saveEvent (event * eventData , dirPath string , now time. Time ) {
454439 if _ , ok := f .Folders [dirPath ]; ok {
455440 // f.Debugf("Item Updated: %v", event.file)
456- f .Folders [dirPath ].updated = time . Now ()
441+ f .Folders [dirPath ].updated = now
457442 return
458443 }
459444
@@ -468,23 +453,23 @@ func (f *Folders) saveEvent(event *eventData, dirPath string) {
468453 f .Printf ("[Folder] Tracking New Item: %v (event: %s)" , dirPath , event .op )
469454
470455 f .Folders [dirPath ] = & Folder {
471- updated : time . Now () ,
456+ updated : now ,
472457 status : WAITING ,
473458 config : event .cnfg ,
474459 }
475460}
476461
477462// checkFolderStats runs at an interval to see if any folders need work done on them.
478463// This runs on an interval ticker in the main go routine.
479- func (u * Unpackerr ) checkFolderStats () {
464+ func (u * Unpackerr ) checkFolderStats (now time. Time ) {
480465 for name , folder := range u .folders .Folders {
481- switch elapsed := time . Since (folder .updated ); {
466+ switch elapsed := now . Sub (folder .updated ); {
482467 case WAITING == folder .status && elapsed >= u .StartDelay .Duration :
483468 // The folder hasn't been written to in a while, extract it.
484- u .extractTrackedItem (name , folder )
469+ u .extractTrackedItem (name , folder , now )
485470 case EXTRACTEDNOTHING == folder .status :
486471 // Wait until this item hasn't been touched for a while, so it doesn't re-queue.
487- if time . Since (folder .updated ) > u .StartDelay .Duration {
472+ if now . Sub (folder .updated ) > u .StartDelay .Duration {
488473 // Ignore "no compressed files" errors for folders.
489474 delete (u .Map , name )
490475 delete (u .folders .Folders , name )
@@ -493,24 +478,24 @@ func (u *Unpackerr) checkFolderStats() {
493478 (u .MaxRetries == 0 || folder .retries < u .MaxRetries ):
494479 u .Retries ++
495480 folder .retries ++
496- folder .updated = time . Now ()
481+ folder .updated = now
497482 folder .status = WAITING
498483 u .Printf ("[Folder] Re-starting Failed Extraction: %s (%d/%d, failed %v ago)" ,
499484 folder .config .Path , folder .retries , u .MaxRetries , elapsed .Round (time .Second ))
500485 case EXTRACTFAILED == folder .status && folder .retries < u .MaxRetries :
501486 // This empty block is to avoid deleting an item that needs more retries.
502487 case folder .status > EXTRACTING && folder .config .DeleteAfter .Duration <= 0 :
503488 // if DeleteAfter is 0 we don't delete anything. we are done.
504- u .updateQueueStatus (& newStatus {Name : name , Status : DELETED , Resp : nil }, false )
489+ u .updateQueueStatus (& newStatus {Name : name , Status : DELETED , Resp : nil }, now , false )
505490 delete (u .folders .Folders , name )
506491 case EXTRACTED == folder .status && elapsed >= folder .config .DeleteAfter .Duration :
507- u .deleteAfterReached (name , folder )
492+ u .deleteAfterReached (name , now , folder )
508493 }
509494 }
510495}
511496
512497//nolint:wsl
513- func (u * Unpackerr ) deleteAfterReached (name string , folder * Folder ) {
498+ func (u * Unpackerr ) deleteAfterReached (name string , now time. Time , folder * Folder ) {
514499 var webhook bool
515500
516501 // Folder reached delete delay (after extraction), nuke it.
@@ -526,11 +511,11 @@ func (u *Unpackerr) deleteAfterReached(name string, folder *Folder) {
526511 u .delChan <- & fileDeleteReq {Paths : []string {name }}
527512 webhook = true
528513 } else if folder .config .DeleteOrig && len (folder .archives ) > 0 {
529- u .delChan <- & fileDeleteReq {Paths : folder .archives }
514+ u .delChan <- & fileDeleteReq {Paths : folder .archives . List () }
530515 webhook = true
531516 }
532517
533- u .updateQueueStatus (& newStatus {Name : name , Status : DELETED , Resp : nil }, webhook )
518+ u .updateQueueStatus (& newStatus {Name : name , Status : DELETED , Resp : nil }, now , webhook )
534519 // Folder reached delete delay (after extraction), nuke it.
535520 delete (u .folders .Folders , name )
536521}
@@ -544,15 +529,15 @@ type newStatus struct {
544529// updateQueueStatus for an on-going tracked extraction.
545530// This is called from a channel callback to update status in a single go routine.
546531// This is used by apps and Folders in a few other places as well.
547- func (u * Unpackerr ) updateQueueStatus (data * newStatus , sendHook bool ) {
532+ func (u * Unpackerr ) updateQueueStatus (data * newStatus , now time. Time , sendHook bool ) {
548533 if _ , ok := u .Map [data .Name ]; ! ok {
549534 // This is a new Folder being queued for extraction.
550535 // Arr apps do not land here. They create their own queued items in u.Map.
551536 u .Map [data .Name ] = & Extract {
552537 Path : data .Name ,
553538 App : FolderString ,
554539 Status : QUEUED ,
555- Updated : time . Now () ,
540+ Updated : now ,
556541 IDs : map [string ]interface {}{"title" : data .Name }, // required or webhook may break.
557542 }
558543
@@ -568,7 +553,7 @@ func (u *Unpackerr) updateQueueStatus(data *newStatus, sendHook bool) {
568553 }
569554
570555 u .Map [data .Name ].Status = data .Status
571- u .Map [data .Name ].Updated = time . Now ()
556+ u .Map [data .Name ].Updated = now
572557
573558 if sendHook {
574559 u .runAllHooks (u .Map [data .Name ])
0 commit comments