diff --git a/apps/backend/db/handler.go b/apps/backend/db/handler.go index 95eb32f..7a3c25f 100644 --- a/apps/backend/db/handler.go +++ b/apps/backend/db/handler.go @@ -1,14 +1,10 @@ package db import ( - "backend/typedefs" - "backend/utils" "context" "fmt" "log/slog" - "os" - "github.com/georgysavva/scany/v2/pgxscan" pgxuuid "github.com/jackc/pgx-gofrs-uuid" "github.com/jackc/pgx/v5" "github.com/jackc/pgx/v5/pgxpool" @@ -19,17 +15,24 @@ type DbHandler struct { Ctx context.Context } -func NewDbHandler() *DbHandler { +type Configs struct { + Host string + Dbname string + Port string + User string + Password string +} + +func NewDbHandler(configs Configs) *DbHandler { fmt.Println("Connecting to db") ctx := context.Background() - host := os.Getenv("PGHOST") - dbname := os.Getenv("POSTGRES_DB") - dbport := os.Getenv("PGPORT") - pguser := os.Getenv("POSTGRES_USER") - pgpassword := os.Getenv("POSTGRES_PASSWORD") + if configs.Host == "" || configs.Dbname == "" || configs.Port == "" || configs.User == "" || configs.Password == "" { + fmt.Println("Environment variables for database connection are not set") + return nil + } - connStr := fmt.Sprintf("postgresql://%s:%s@%s:%s/%s?sslmode=disable", pguser, pgpassword, host, dbport, dbname) + connStr := fmt.Sprintf("postgresql://%s:%s@%s:%s/%s?sslmode=disable", configs.User, configs.Password, configs.Host, configs.Port, configs.Dbname) fmt.Printf("Connecting to db with connection string: %s", connStr) config, err := pgxpool.ParseConfig(connStr) if err != nil { @@ -49,263 +52,3 @@ func NewDbHandler() *DbHandler { return &DbHandler{Dbpool: dbpool, Ctx: ctx} } - -func (h *DbHandler) GetActiveAnnunci() []string { - var annunci []string - pgxscan.Select(h.Ctx, h.Dbpool, &annunci, "SELECT codice FROM public.annunci WHERE web = true and stato = 'Attivo' ") - /*for i, annuncio := range annunci { - //if first letter is V then set annuncio as the last 4 digits - if string(annuncio[0]) != "V" { - annunci[i] = annuncio[:4] - } - }*/ - return annunci -} - -func (h *DbHandler) GetAllAnnunci() []typedefs.AnnunciDB { - //var annuncio AnnunciDB - var annunci []typedefs.AnnunciDB - - pgxscan.Select(h.Ctx, h.Dbpool, &annunci, "SELECT * FROM public.annunci") - return annunci - -} - -func (h *DbHandler) InsertAnnunciInDB(annunci typedefs.AnnunciParsed) { - - //SET ALL WEB TO FALSE - _, err := h.Dbpool.Exec(h.Ctx, "UPDATE public.annunci SET web = false") - if err != nil { - panic(err) - - } - //GET ALL CODICI - var codici []string - err = pgxscan.Select(h.Ctx, h.Dbpool, &codici, "SELECT DISTINCT codice FROM public.annunci") - if err != nil { - panic(err) - } - batch := &pgx.Batch{} - for _, annuncio := range annunci.Annuncio { - - if utils.Contains(codici, annuncio.Codice) { - batch.Queue(` - UPDATE public.annunci - SET locatore = $1, - numero = $2, - idlocatore = $3, - email = $4, - creato_il = $5, - modificato_il = $6, - indirizzo = $7, - civico = $8, - comune = $9, - cap = $10, - provincia = $11, - regione = $12, - lat = $13, - lon = $14, - indirizzo_secondario = $15, - civico_secondario = $16, - lat_secondario = $17, - lon_secondario = $18, - tipo = $19, - categorie = $20, - prezzo = $21, - anno = $22, - consegna = $23, - classe = $24, - mq = $25, - piano = $26, - piano_palazzo = $27, - unita_condominio = $28, - numero_vani = $29, - numero_camere = $30, - numero_bagni = $31, - numero_balconi = $32, - numero_terrazzi = $33, - numero_box = $34, - numero_postiauto = $35, - caratteristiche = $36, - accessori = $37, - titolo_it = $38, - desc_it = $39, - titolo_en = $40, - desc_en = $41, - stato = $42, - web = $43, - homepage = $44, - url_immagini = $45, - url_video = $46, - og_url = $48 - WHERE codice = $47 - `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, - annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, - annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap, - annuncio.Provincia, annuncio.Regione, annuncio.Lat, annuncio.Lon, - annuncio.Indirizzo_secondario, annuncio.Civico_secondario, annuncio.Lat_secondario, - annuncio.Lon_secondario, annuncio.Tipo, annuncio.Categorie, annuncio.Prezzo, annuncio.Anno, - annuncio.Consegna, annuncio.Classe, annuncio.Mq, annuncio.Piano, annuncio.Piano_palazzo, - annuncio.Unita_condominio, annuncio.Numero_vani, annuncio.Numero_camere, annuncio.Numero_bagni, - annuncio.Numero_balconi, annuncio.Numero_terrazzi, annuncio.Numero_box, annuncio.Numero_postiauto, - annuncio.Caratteristiche, annuncio.Accessori, annuncio.Titolo_it, annuncio.Desc_it, annuncio.Titolo_en, - annuncio.Desc_en, annuncio.Stato, annuncio.Web, annuncio.Homepage, annuncio.Url_foto, - annuncio.Url_video, annuncio.Codice, annuncio.Og_url) - - } else { - batch.Queue(` - INSERT INTO public.annunci( - locatore, - numero, - idlocatore, - email, - creato_il, - modificato_il, - indirizzo, - civico, - comune, - cap, - provincia, - regione, - lat, - lon, - indirizzo_secondario, - civico_secondario, - lat_secondario, - lon_secondario, - tipo, - categorie, - prezzo, - anno, - consegna, - classe, - mq, - piano, - piano_palazzo, - unita_condominio, - numero_vani, - numero_camere, - numero_bagni, - numero_balconi, - numero_terrazzi, - numero_box, - numero_postiauto, - caratteristiche, - accessori, - titolo_it, - desc_it, - titolo_en, - desc_en, - stato, - web, - homepage, - url_immagini, - url_video, - codice, - og_url - ) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47, $48) - `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, - annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, - annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap, - annuncio.Provincia, annuncio.Regione, annuncio.Lat, annuncio.Lon, - annuncio.Indirizzo_secondario, annuncio.Civico_secondario, annuncio.Lat_secondario, - annuncio.Lon_secondario, annuncio.Tipo, annuncio.Categorie, annuncio.Prezzo, annuncio.Anno, - annuncio.Consegna, annuncio.Classe, annuncio.Mq, annuncio.Piano, annuncio.Piano_palazzo, - annuncio.Unita_condominio, annuncio.Numero_vani, annuncio.Numero_camere, annuncio.Numero_bagni, - annuncio.Numero_balconi, annuncio.Numero_terrazzi, annuncio.Numero_box, annuncio.Numero_postiauto, - annuncio.Caratteristiche, annuncio.Accessori, annuncio.Titolo_it, annuncio.Desc_it, annuncio.Titolo_en, - annuncio.Desc_en, annuncio.Stato, annuncio.Web, annuncio.Homepage, annuncio.Url_foto, - annuncio.Url_video, annuncio.Codice, annuncio.Og_url) - - } - } - results := h.Dbpool.SendBatch(h.Ctx, batch).Close() - fmt.Println(results) - -} - -func (h *DbHandler) ClearRecords() { - - //SET ALL WEB TO FALSE - _, err := h.Dbpool.Exec(h.Ctx, "DELETE FROM public.annunci") - if err != nil { - panic(err) - - } -} - -func (h *DbHandler) SetFromBkp(annunci typedefs.AnnunciParsed) { - h.ClearRecords() - - batch := &pgx.Batch{} - for _, annuncio := range annunci.Annuncio { - batch.Queue(` - INSERT INTO public.annunci( - locatore, - numero, - idlocatore, - email, - creato_il, - modificato_il, - indirizzo, - civico, - comune, - cap, - provincia, - regione, - lat, - lon, - indirizzo_secondario, - civico_secondario, - lat_secondario, - lon_secondario, - tipo, - categorie, - prezzo, - anno, - consegna, - classe, - mq, - piano, - piano_palazzo, - unita_condominio, - numero_vani, - numero_camere, - numero_bagni, - numero_balconi, - numero_terrazzi, - numero_box, - numero_postiauto, - caratteristiche, - accessori, - titolo_it, - desc_it, - titolo_en, - desc_en, - stato, - web, - homepage, - url_immagini, - url_video, - codice - ) - VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47) - `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, - annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, - annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap, - annuncio.Provincia, annuncio.Regione, annuncio.Lat, annuncio.Lon, - annuncio.Indirizzo_secondario, annuncio.Civico_secondario, annuncio.Lat_secondario, - annuncio.Lon_secondario, annuncio.Tipo, annuncio.Categorie, annuncio.Prezzo, annuncio.Anno, - annuncio.Consegna, annuncio.Classe, annuncio.Mq, annuncio.Piano, annuncio.Piano_palazzo, - annuncio.Unita_condominio, annuncio.Numero_vani, annuncio.Numero_camere, annuncio.Numero_bagni, - annuncio.Numero_balconi, annuncio.Numero_terrazzi, annuncio.Numero_box, annuncio.Numero_postiauto, - annuncio.Caratteristiche, annuncio.Accessori, annuncio.Titolo_it, annuncio.Desc_it, annuncio.Titolo_en, - annuncio.Desc_en, annuncio.Stato, annuncio.Web, annuncio.Homepage, annuncio.Url_foto, - annuncio.Url_video, annuncio.Codice) - - } - results := h.Dbpool.SendBatch(h.Ctx, batch).Close() - fmt.Println(results) - -} diff --git a/apps/backend/db/helpers.go b/apps/backend/db/helpers.go index b6a8f84..a531c43 100644 --- a/apps/backend/db/helpers.go +++ b/apps/backend/db/helpers.go @@ -51,11 +51,6 @@ func ConnectToDatabaseWithLogging(ctx context.Context, connectionString string, return pool, nil } -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - var ( replaceTabs = regexp.MustCompile(`\t+`) replaceSpacesBeforeOpeningParens = regexp.MustCompile(`\s+\(`) @@ -118,11 +113,6 @@ func (l *LoggingQueryTracer) TraceQueryEnd(ctx context.Context, conn *pgx.Conn, ) } -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// -//////////////////////////////////////////////////////////////////////////////// - // https://github.com/jackc/pgx/discussions/1677#discussioncomment-8815982 type MultiQueryTracer struct { Tracers []pgx.QueryTracer diff --git a/apps/backend/image_handler.go b/apps/backend/image_handler.go index 7b9b1be..bf08e1e 100644 --- a/apps/backend/image_handler.go +++ b/apps/backend/image_handler.go @@ -1,14 +1,12 @@ package main import ( + "backend/queries" "backend/typedefs" "fmt" "log" "os" "path/filepath" - - "github.com/georgysavva/scany/v2/pgxscan" - "github.com/jackc/pgx/v5" ) type ImageRefManager struct { @@ -18,39 +16,17 @@ func NewImageRefManager() *ImageRefManager { return &ImageRefManager{} } -func (i *ImageRefManager) GetImagesRef() ([]typedefs.MiogestImagesRef_Table, error) { - - var images []typedefs.MiogestImagesRef_Table - - err := pgxscan.Select(Db.Ctx, Db.Dbpool, &images, "SELECT * FROM public.miogest_images_ref") - if err != nil { - return nil, err - } - - return images, nil -} +// func (i *ImageRefManager) GetImagesRef() ([]typedefs.MiogestImagesRef_Table, error) { +// return queries.ImagesGetAll() +// } func (i *ImageRefManager) InsertImagesRef(annunci *typedefs.AnnunciXML) error { - batch := &pgx.Batch{} - - for _, annuncio := range annunci.Annuncio { - batch.Queue(` - INSERT INTO public.miogest_images_ref (codice, foto) - VALUES ($1, $2) - ON CONFLICT (codice) DO UPDATE SET foto = $2 - `, &annuncio.Codice, &annuncio.Foto) - } - - if err := Db.Dbpool.SendBatch(Db.Ctx, batch).Close(); err != nil { - return err - } - - return nil + return queries.ImagesBatchInsert(annunci) } func (i *ImageRefManager) FindIsUpdate(annunci *typedefs.AnnunciXML) ([]string, error) { - r, err := i.GetImagesRef() + r, err := queries.ImagesGetAll() if err != nil { return nil, err } @@ -104,13 +80,12 @@ func (i *ImageRefManager) ClearImages(to_clear []string) error { } func (i *ImageRefManager) Reset() error { - - _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.miogest_images_ref") + err := queries.ImagesClear() if err != nil { return err } - _, err = Db.Dbpool.Exec(Db.Ctx, "UPDATE public.annunci SET url_immagini = NULL, url_video = NULL") + err = queries.AnnunciResetImages() if err != nil { return err } diff --git a/apps/backend/images.go b/apps/backend/images.go index bcdf4b1..7c1f82a 100644 --- a/apps/backend/images.go +++ b/apps/backend/images.go @@ -1,6 +1,7 @@ package main import ( + "backend/queries" "bytes" "fmt" "image" @@ -119,7 +120,10 @@ func ImageRoutes(e *echo.Echo) { }) e.GET("/images/list", func(c echo.Context) error { - annunci := Db.GetActiveAnnunci() + annunci, err := queries.AnnunciGetActive() + if err != nil { + return c.String(http.StatusInternalServerError, err.Error()) + } return c.JSON(http.StatusOK, annunci) }) diff --git a/apps/backend/queries/annunci.go b/apps/backend/queries/annunci.go new file mode 100644 index 0000000..36495fa --- /dev/null +++ b/apps/backend/queries/annunci.go @@ -0,0 +1,271 @@ +package queries + +import ( + "backend/typedefs" + "backend/utils" + "fmt" + + "github.com/georgysavva/scany/v2/pgxscan" + "github.com/jackc/pgx/v5" +) + +func AnnunciGetActive() ([]string, error) { + var annunci []string + err := pgxscan.Select(Db.Ctx, Db.Dbpool, &annunci, "SELECT codice FROM public.annunci WHERE web = true and stato = 'Attivo' ") + if err != nil && err != pgx.ErrNoRows { + return nil, fmt.Errorf("failed to get active annunci: %w", err) + } + return annunci, nil +} + +func AnnunciInsert(annunci typedefs.AnnunciParsed) error { + + //SET ALL WEB TO FALSE + _, err := Db.Dbpool.Exec(Db.Ctx, "UPDATE public.annunci SET web = false") + if err != nil { + return fmt.Errorf("failed to set all web to false: %w", err) + + } + //GET ALL CODICI + var codici []string + err = pgxscan.Select(Db.Ctx, Db.Dbpool, &codici, "SELECT DISTINCT codice FROM public.annunci") + if err != nil { + return fmt.Errorf("failed to get all codici: %w", err) + } + batch := &pgx.Batch{} + for _, annuncio := range annunci.Annuncio { + + if utils.Contains(codici, annuncio.Codice) { + batch.Queue(` + UPDATE public.annunci + SET locatore = $1, + numero = $2, + idlocatore = $3, + email = $4, + creato_il = $5, + modificato_il = $6, + indirizzo = $7, + civico = $8, + comune = $9, + cap = $10, + provincia = $11, + regione = $12, + lat = $13, + lon = $14, + indirizzo_secondario = $15, + civico_secondario = $16, + lat_secondario = $17, + lon_secondario = $18, + tipo = $19, + categorie = $20, + prezzo = $21, + anno = $22, + consegna = $23, + classe = $24, + mq = $25, + piano = $26, + piano_palazzo = $27, + unita_condominio = $28, + numero_vani = $29, + numero_camere = $30, + numero_bagni = $31, + numero_balconi = $32, + numero_terrazzi = $33, + numero_box = $34, + numero_postiauto = $35, + caratteristiche = $36, + accessori = $37, + titolo_it = $38, + desc_it = $39, + titolo_en = $40, + desc_en = $41, + stato = $42, + web = $43, + homepage = $44, + url_immagini = $45, + url_video = $46, + og_url = $48 + WHERE codice = $47 + `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, + annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, + annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap, + annuncio.Provincia, annuncio.Regione, annuncio.Lat, annuncio.Lon, + annuncio.Indirizzo_secondario, annuncio.Civico_secondario, annuncio.Lat_secondario, + annuncio.Lon_secondario, annuncio.Tipo, annuncio.Categorie, annuncio.Prezzo, annuncio.Anno, + annuncio.Consegna, annuncio.Classe, annuncio.Mq, annuncio.Piano, annuncio.Piano_palazzo, + annuncio.Unita_condominio, annuncio.Numero_vani, annuncio.Numero_camere, annuncio.Numero_bagni, + annuncio.Numero_balconi, annuncio.Numero_terrazzi, annuncio.Numero_box, annuncio.Numero_postiauto, + annuncio.Caratteristiche, annuncio.Accessori, annuncio.Titolo_it, annuncio.Desc_it, annuncio.Titolo_en, + annuncio.Desc_en, annuncio.Stato, annuncio.Web, annuncio.Homepage, annuncio.Url_foto, + annuncio.Url_video, annuncio.Codice, annuncio.Og_url) + + } else { + batch.Queue(` + INSERT INTO public.annunci( + locatore, + numero, + idlocatore, + email, + creato_il, + modificato_il, + indirizzo, + civico, + comune, + cap, + provincia, + regione, + lat, + lon, + indirizzo_secondario, + civico_secondario, + lat_secondario, + lon_secondario, + tipo, + categorie, + prezzo, + anno, + consegna, + classe, + mq, + piano, + piano_palazzo, + unita_condominio, + numero_vani, + numero_camere, + numero_bagni, + numero_balconi, + numero_terrazzi, + numero_box, + numero_postiauto, + caratteristiche, + accessori, + titolo_it, + desc_it, + titolo_en, + desc_en, + stato, + web, + homepage, + url_immagini, + url_video, + codice, + og_url + ) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47, $48) + `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, + annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, + annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap, + annuncio.Provincia, annuncio.Regione, annuncio.Lat, annuncio.Lon, + annuncio.Indirizzo_secondario, annuncio.Civico_secondario, annuncio.Lat_secondario, + annuncio.Lon_secondario, annuncio.Tipo, annuncio.Categorie, annuncio.Prezzo, annuncio.Anno, + annuncio.Consegna, annuncio.Classe, annuncio.Mq, annuncio.Piano, annuncio.Piano_palazzo, + annuncio.Unita_condominio, annuncio.Numero_vani, annuncio.Numero_camere, annuncio.Numero_bagni, + annuncio.Numero_balconi, annuncio.Numero_terrazzi, annuncio.Numero_box, annuncio.Numero_postiauto, + annuncio.Caratteristiche, annuncio.Accessori, annuncio.Titolo_it, annuncio.Desc_it, annuncio.Titolo_en, + annuncio.Desc_en, annuncio.Stato, annuncio.Web, annuncio.Homepage, annuncio.Url_foto, + annuncio.Url_video, annuncio.Codice, annuncio.Og_url) + } + } + err = Db.Dbpool.SendBatch(Db.Ctx, batch).Close() + if err != nil { + return fmt.Errorf("failed to insert/update annunci batch: %w", err) + } + fmt.Println("Annunci insert/update done") + return nil +} + +func clearRecords() { + + //SET ALL WEB TO FALSE + _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.annunci") + if err != nil { + panic(err) + + } +} + +func SetFromBkp(annunci typedefs.AnnunciParsed) error { + clearRecords() + + batch := &pgx.Batch{} + for _, annuncio := range annunci.Annuncio { + batch.Queue(` + INSERT INTO public.annunci( + locatore, + numero, + idlocatore, + email, + creato_il, + modificato_il, + indirizzo, + civico, + comune, + cap, + provincia, + regione, + lat, + lon, + indirizzo_secondario, + civico_secondario, + lat_secondario, + lon_secondario, + tipo, + categorie, + prezzo, + anno, + consegna, + classe, + mq, + piano, + piano_palazzo, + unita_condominio, + numero_vani, + numero_camere, + numero_bagni, + numero_balconi, + numero_terrazzi, + numero_box, + numero_postiauto, + caratteristiche, + accessori, + titolo_it, + desc_it, + titolo_en, + desc_en, + stato, + web, + homepage, + url_immagini, + url_video, + codice + ) + VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44, $45, $46, $47) + `, annuncio.Locatore, annuncio.Numero, annuncio.Idlocatore, + annuncio.Email, annuncio.Creato_il, annuncio.Modificato_il, + annuncio.Indirizzo, annuncio.Civico, annuncio.Comune, annuncio.Cap, + annuncio.Provincia, annuncio.Regione, annuncio.Lat, annuncio.Lon, + annuncio.Indirizzo_secondario, annuncio.Civico_secondario, annuncio.Lat_secondario, + annuncio.Lon_secondario, annuncio.Tipo, annuncio.Categorie, annuncio.Prezzo, annuncio.Anno, + annuncio.Consegna, annuncio.Classe, annuncio.Mq, annuncio.Piano, annuncio.Piano_palazzo, + annuncio.Unita_condominio, annuncio.Numero_vani, annuncio.Numero_camere, annuncio.Numero_bagni, + annuncio.Numero_balconi, annuncio.Numero_terrazzi, annuncio.Numero_box, annuncio.Numero_postiauto, + annuncio.Caratteristiche, annuncio.Accessori, annuncio.Titolo_it, annuncio.Desc_it, annuncio.Titolo_en, + annuncio.Desc_en, annuncio.Stato, annuncio.Web, annuncio.Homepage, annuncio.Url_foto, + annuncio.Url_video, annuncio.Codice) + + } + err := Db.Dbpool.SendBatch(Db.Ctx, batch).Close() + if err != nil { + return fmt.Errorf("failed to insert/update annunci batch: %w", err) + } + fmt.Println("Annunci insert/update done") + return nil +} + +func AnnunciResetImages() error { + _, err := Db.Dbpool.Exec(Db.Ctx, "UPDATE public.annunci SET url_immagini = NULL, url_video = NULL") + if err != nil { + return fmt.Errorf("failed to reset images: %w", err) + } + return nil +} diff --git a/apps/backend/queries/images.go b/apps/backend/queries/images.go new file mode 100644 index 0000000..115807e --- /dev/null +++ b/apps/backend/queries/images.go @@ -0,0 +1,44 @@ +package queries + +import ( + "backend/typedefs" + "fmt" + + "github.com/georgysavva/scany/v2/pgxscan" + "github.com/jackc/pgx/v5" +) + +func ImagesGetAll() ([]typedefs.MiogestImagesRef_Table, error) { + var images []typedefs.MiogestImagesRef_Table + err := pgxscan.Select(Db.Ctx, Db.Dbpool, &images, "SELECT * FROM public.miogest_images_ref") + if err != nil && err != pgx.ErrNoRows { + return nil, fmt.Errorf("failed to get all images: %w", err) + } + return images, nil +} + +func ImagesBatchInsert(annunci *typedefs.AnnunciXML) error { + batch := &pgx.Batch{} + + for _, annuncio := range annunci.Annuncio { + batch.Queue(` + INSERT INTO public.miogest_images_ref (codice, foto) + VALUES ($1, $2) + ON CONFLICT (codice) DO UPDATE SET foto = $2 + `, &annuncio.Codice, &annuncio.Foto) + } + + if err := Db.Dbpool.SendBatch(Db.Ctx, batch).Close(); err != nil { + return fmt.Errorf("failed to insert/update images batch: %w", err) + } + + return nil +} + +func ImagesClear() error { + _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.miogest_images_ref") + if err != nil { + return fmt.Errorf("failed to clear images: %w", err) + } + return nil +} diff --git a/apps/backend/queries/queries.go b/apps/backend/queries/queries.go new file mode 100644 index 0000000..6b284cb --- /dev/null +++ b/apps/backend/queries/queries.go @@ -0,0 +1,34 @@ +package queries + +import ( + "backend/db" + "os" + + "github.com/joho/godotenv" +) + +var ( + Db *db.DbHandler +) + +func init() { + _ = godotenv.Load(".env") + + Db = db.NewDbHandler(db.Configs{ + Host: os.Getenv("PGHOST"), + Dbname: os.Getenv("POSTGRES_DB"), + Port: os.Getenv("PGPORT"), + User: os.Getenv("POSTGRES_USER"), + Password: os.Getenv("POSTGRES_PASSWORD"), + }) + +} + +func HealthCheck() bool { + if Db == nil || Db.Dbpool == nil { + return false + } + err := Db.Dbpool.Ping(Db.Ctx) + return err == nil + +} diff --git a/apps/backend/queries/storage.go b/apps/backend/queries/storage.go new file mode 100644 index 0000000..d4b8571 --- /dev/null +++ b/apps/backend/queries/storage.go @@ -0,0 +1,95 @@ +package queries + +import ( + "backend/typedefs" + "fmt" + "time" + + "github.com/georgysavva/scany/v2/pgxscan" +) + +// STORAGE + +func StorageNewId() (string, error) { + var newId string + err := Db.Dbpool.QueryRow(Db.Ctx, "INSERT INTO public.storageindex(filename)VALUES (null) RETURNING id;").Scan(&newId) + if err != nil { + return "", err + } + if newId == "" { + return "", fmt.Errorf("failed to create new id") + } + return newId, nil + +} + +func StorageGet_min() ([]struct { + Id string + Ext string +}, error) { + var items_db []struct { + Id string + Ext string + } + + err := pgxscan.Select(Db.Ctx, Db.Dbpool, &items_db, "SELECT id, ext FROM public.storageindex") + if err != nil { + return nil, fmt.Errorf("failed to get items: %w", err) + } + return items_db, nil +} + +func StorageUpdate(id, filename, ext string, from_admin bool, expires_at *time.Time) error { + _, err := Db.Dbpool.Exec(Db.Ctx, "UPDATE public.storageindex set filename= $2, ext = $3, from_admin = $4, expires_at = $5 where id = $1", id, filename, ext, from_admin, expires_at) + if err != nil { + return fmt.Errorf("failed to update storage index: %w", err) + } + return nil +} + +func StorageDelete(id string) error { + _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.storageindex WHERE id = $1", id) + if err != nil { + return fmt.Errorf("failed to delete storage index: %w", err) + } + return nil + +} + +func StorageDeleteUnused() error { + _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.storageindex WHERE filename IS NULL") + if err != nil { + return fmt.Errorf("failed to delete storage index: %w", err) + } + return nil +} + +func StorageCheckToken(token string) error { + var tk []string + err := pgxscan.Select(Db.Ctx, Db.Dbpool, &tk, "SELECT token FROM public.temp_tokens WHERE token = $1 and elapse > $2", token, time.Now()) + if err != nil { + return fmt.Errorf("failed to check token: %w", err) + } + if tk == nil { + return fmt.Errorf("invalid or expired token") + } + return nil +} + +func StorageCleanExpiredTokens(token string) error { + _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.temp_tokens WHERE elapse < $1", time.Now()) + if err != nil { + return err + } + return nil +} + +func StorageGetExpiredFiles() ([]typedefs.Storageindex, error) { + + var items_db []typedefs.Storageindex + err := pgxscan.Select(Db.Ctx, Db.Dbpool, &items_db, "SELECT * FROM public.storageindex WHERE expires_at is not null and expires_at < NOW()") + if err != nil { + return nil, fmt.Errorf("failed to get expired items: %w", err) + } + return items_db, nil +} diff --git a/apps/backend/server.go b/apps/backend/server.go index 1781abd..8bafb3a 100644 --- a/apps/backend/server.go +++ b/apps/backend/server.go @@ -1,7 +1,7 @@ package main import ( - "backend/db" + "backend/queries" storagehandlers "backend/storage_handlers" "fmt" "io" @@ -24,7 +24,6 @@ var ( imageOption bool concurrentImages int = 1 storagepath string - Db *db.DbHandler Miogest *MiogestHandler ImageManager *ImageRefManager Storage storagehandlers.StorageHandler @@ -63,13 +62,6 @@ func main() { } } - // SETUP DATABASE HANDLER - Db = db.NewDbHandler() - if Db == nil { - log.Fatal("Error connecting to db") - } - defer Db.Dbpool.Close() - // SETUP MIOGEST HANDLER Miogest = NewMiogestHandler() if Miogest == nil { @@ -170,11 +162,8 @@ func SetupRoutes() *echo.Echo { return c.String(http.StatusOK, "OK") }) e.GET("/health", func(c echo.Context) error { - _, err := Db.Dbpool.Exec(Db.Ctx, "SELECT 1") - if err != nil { - panic(err) - } - return c.String(http.StatusOK, "success") + h := queries.HealthCheck() + return c.String(http.StatusOK, fmt.Sprintf("DB Connection: %v", h)) }) MiogestRoutes(e) @@ -219,7 +208,10 @@ func BkpRoutes(e *echo.Echo) { }) e.GET("/setbkp", func(c echo.Context) error { var data = ParseUpdateBkp() - Db.SetFromBkp(data) + err := queries.SetFromBkp(data) + if err != nil { + return c.String(http.StatusInternalServerError, err.Error()) + } return c.String(http.StatusOK, "Setted") }) } @@ -255,7 +247,10 @@ func MiogestRoutes(e *echo.Echo) { }) e.GET("/update", func(c echo.Context) error { var data = Miogest.GetAnnunciParsed() - Db.InsertAnnunciInDB(data) + err := queries.AnnunciInsert(data) + if err != nil { + return c.String(http.StatusInternalServerError, err.Error()) + } return c.String(http.StatusOK, "Updated") }) } diff --git a/apps/backend/storage.go b/apps/backend/storage.go index ee53f78..c88c0a3 100644 --- a/apps/backend/storage.go +++ b/apps/backend/storage.go @@ -1,8 +1,7 @@ package main import ( - "backend/typedefs" - "errors" + "backend/queries" "fmt" "log" "mime/multipart" @@ -12,22 +11,18 @@ import ( "slices" "time" - "github.com/georgysavva/scany/v2/pgxscan" "github.com/labstack/echo/v4" ) // Upload saves a file to the storage directory. func Upload(file *multipart.FileHeader, from_admin bool) (string, error) { log.Printf("Uploading file: %s", file.Filename) - log.Printf("DB instance: %v", Db.Dbpool) - var newId string - err := Db.Dbpool.QueryRow(Db.Ctx, "INSERT INTO public.storageindex(filename)VALUES (null) RETURNING id;").Scan(&newId) + + newId, err := queries.StorageNewId() if err != nil { - log.Fatal(err) - } - if newId == "" { - return "", errors.New("failed to create new id") + return "", err } + err = Storage.Add(file, newId) if err != nil { return "", err @@ -41,14 +36,14 @@ func Upload(file *multipart.FileHeader, from_admin bool) (string, error) { expiresAt = nil } - _, err = Db.Dbpool.Exec(Db.Ctx, "UPDATE public.storageindex set filename= $2, ext = $3, from_admin = $4, expires_at = $5 where id = $1", newId, file.Filename, filepath.Ext(file.Filename), from_admin, expiresAt) + err = queries.StorageUpdate(newId, file.Filename, filepath.Ext(file.Filename), from_admin, expiresAt) if err != nil { - log.Fatal(err) + return "", err } - _, err = Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.storageindex WHERE filename IS NULL") + err = queries.StorageDeleteUnused() if err != nil { - log.Fatal(err) + return "", err } return newId, nil @@ -59,16 +54,12 @@ func StorageAuth(c echo.Context) error { if len(token) < 1 { return c.String(http.StatusUnauthorized, "Unauthorized") } - var tk []string - err := pgxscan.Select(Db.Ctx, Db.Dbpool, &tk, "SELECT token FROM public.temp_tokens WHERE token = $1 and elapse > $2", token, time.Now()) + err := queries.StorageCheckToken(token) if err != nil { return err } - if tk == nil { - return errors.New("invalid token") - } - _, err = Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.temp_tokens WHERE elapse < $1", time.Now()) + err = queries.StorageCleanExpiredTokens(token) if err != nil { return err } @@ -77,29 +68,25 @@ func StorageAuth(c echo.Context) error { func RemoveFromDb(ref string) error { - _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.storageindex WHERE id = $1", ref) - if err != nil { - return err - } - return nil + return queries.StorageDelete(ref) } func RemoveExpired() error { //get all expired files - var items_db []typedefs.Storageindex - err := pgxscan.Select(Db.Ctx, Db.Dbpool, &items_db, "SELECT * FROM public.storageindex WHERE expires_at is not null and expires_at < NOW()") + items_db, err := queries.StorageGetExpiredFiles() if err != nil { - return fmt.Errorf("failed to get expired items: %w", err) + return err } + for _, item := range items_db { formattedName := item.Id + item.Ext err = Storage.Delete(formattedName) if err != nil { return fmt.Errorf("failed to delete file %s: %w", formattedName, err) } - err = RemoveFromDb(item.Id) + err = queries.StorageDelete(item.Id) if err != nil { - return fmt.Errorf("failed to remove item from db: %w", err) + return err } } @@ -107,13 +94,7 @@ func RemoveExpired() error { } func CheckConcruency() error { - - var items_db []struct { - Id string - Ext string - } - - err := pgxscan.Select(Db.Ctx, Db.Dbpool, &items_db, "SELECT id, ext FROM public.storageindex") + items_db, err := queries.StorageGet_min() if err != nil { return err } @@ -130,13 +111,11 @@ func CheckConcruency() error { if found { founds = append(founds, formattedName) } else { - - _, err := Db.Dbpool.Exec(Db.Ctx, "DELETE FROM public.storageindex WHERE id = $1", item.Id) + err := queries.StorageDelete(item.Id) if err != nil { return err } } - } for _, file := range files { found := slices.Contains(founds, file) @@ -147,7 +126,6 @@ func CheckConcruency() error { } } } - return nil }