github.com/benoitkugler/goacve@v0.0.0-20201217100549-151ce6e55dc8/server/shared/documents_temporaires.go (about)

     1  package shared
     2  
     3  import (
     4  	"database/sql"
     5  	"fmt"
     6  	"net/http"
     7  	"time"
     8  
     9  	rd "github.com/benoitkugler/goACVE/server/core/rawdata"
    10  	"github.com/labstack/echo"
    11  )
    12  
    13  const (
    14  	jour = time.Hour * 24
    15  
    16  	// Le nettoyage des documents temporaires est lancé à intervalles fixes.
    17  	DelayCleanupTmpDocs = jour
    18  )
    19  
    20  // un document temporaire est valide JoursValide
    21  // jours après sa dernière modification
    22  func isDocumentPerime(doc rd.Document, contrainte rd.Contrainte, now time.Time) bool {
    23  	lastModif := doc.DateHeureModif
    24  	timeValid := lastModif.Time().Add(jour * time.Duration(contrainte.JoursValide))
    25  	return now.After(timeValid)
    26  }
    27  
    28  // cherche et supprime les documents liés à des contraintes temporaires et périmés
    29  func cleanupTmpDocuments(db *sql.DB) (string, error) {
    30  	// on commence par sélectionner les contraintes concernées
    31  	rows, err := db.Query("SELECT * FROM contraintes WHERE jours_valide > 0")
    32  	if err != nil {
    33  		return "", err
    34  	}
    35  	contraintes, err := rd.ScanContraintes(rows)
    36  	if err != nil {
    37  		return "", err
    38  	}
    39  
    40  	// on cherche les documents déposés associés, via la table de liens
    41  	// les liens sont nécessaires pour retrouver les contraintes
    42  	liens, err := rd.SelectDocumentPersonnesByIdContraintes(db, contraintes.Ids()...)
    43  	if err != nil {
    44  		return "", err
    45  	}
    46  	// on charge tous les documents liés
    47  	var idsDocs rd.Ids
    48  	for _, lien := range liens {
    49  		idsDocs = append(idsDocs, lien.IdDocument)
    50  	}
    51  	rows, err = db.Query("SELECT * FROM documents WHERE id = ANY($1)", idsDocs.AsSQL())
    52  	if err != nil {
    53  		return "", err
    54  	}
    55  	documents, err := rd.ScanDocuments(rows)
    56  	if err != nil {
    57  		return "", err
    58  	}
    59  
    60  	// on trouve les documents périmés
    61  	var toDelete rd.Ids
    62  	now := time.Now()
    63  	for _, lien := range liens {
    64  		doc := documents[lien.IdDocument]
    65  		contrainte := contraintes[lien.IdContrainte]
    66  		if isDocumentPerime(doc, contrainte, now) {
    67  			toDelete = append(toDelete, doc.Id)
    68  		}
    69  	}
    70  
    71  	out := fmt.Sprintf("Trouvé %d documents périmés pour %d contraintes temporaires\n", len(toDelete), len(contraintes.Ids()))
    72  
    73  	// les liens sont supprimés par cascade
    74  	_, err = rd.DeleteDocumentsByIds(db, toDelete...)
    75  	return out, err
    76  }
    77  
    78  // CleanupTmpDocuments supprimes les documents périmés,
    79  // et devrait être appelé régulièrement.
    80  func (ct Controller) CleanupTmpDocuments(c echo.Context) error {
    81  	status, err := cleanupTmpDocuments(ct.DB)
    82  	code := http.StatusOK
    83  	if err != nil {
    84  		status = "Error : " + err.Error()
    85  		code = http.StatusInternalServerError
    86  	}
    87  	return c.String(code, status)
    88  }