From 1225f861eed80e76b61233dbda9308cabc9053f4 Mon Sep 17 00:00:00 2001 From: Matteo Salvi Date: Sat, 2 Dec 2023 22:23:35 +0100 Subject: [PATCH] fix: removed memory leak and added some try..except --- LidlToGrocy.lpi | 3 -- library/grocy.product.pas | 36 +++++++++++++++++++ library/kernel.application.pas | 27 ++++++++++----- service/grocy.service.pas | 63 +++++++++++++++++++++++++++------- 4 files changed, 104 insertions(+), 25 deletions(-) diff --git a/LidlToGrocy.lpi b/LidlToGrocy.lpi index 788fb1b..a6dd775 100644 --- a/LidlToGrocy.lpi +++ b/LidlToGrocy.lpi @@ -209,9 +209,6 @@ - - - diff --git a/library/grocy.product.pas b/library/grocy.product.pas index f205854..5dc29f5 100644 --- a/library/grocy.product.pas +++ b/library/grocy.product.pas @@ -45,6 +45,7 @@ TGrocyProduct = class(TSynAutoCreateFields) FShouldNotBeFrozen: string; FTreatOpenedAsOutOfStock: string; public + constructor Create(Source: TGrocyProduct); overload; procedure DefaultSetup(); published property Active: string read FActive write FActive; @@ -91,6 +92,41 @@ implementation { TGrocyProduct } +constructor TGrocyProduct.Create(Source: TGrocyProduct); +begin + FActive := Source.Active; + FCalories := Source.Calories; + FCumulateMinStockAmountOfSubProducts := Source.CumulateMinStockAmountOfSubProducts; + FDefaultBestBeforeDays := Source.DefaultBestBeforeDays; + FDefaultBestBeforeDaysAfterFreezing := Source.DefaultBestBeforeDaysAfterFreezing; + FDefaultBestBeforeDaysAfterOpen := Source.DefaultBestBeforeDaysAfterOpen; + FDefaultBestBeforeDaysAfterThawing := Source.DefaultBestBeforeDaysAfterThawing; + FDefaultConsumeLocationId := Source.DefaultConsumeLocationId; + FDescription := Source.Description; + FDueType := Source.DueType; + FEnableTareWeightHandling := Source.EnableTareWeightHandling; + FHideOnStockOverview := Source.HideOnStockOverview; + FId := Source.Id; + FLocationId := Source.LocationId; + FMinStockAmount := Source.MinStockAmount; + FMoveOnOpen := Source.MoveOnOpen; + FName := Source.Name; + FNoOwnStock := Source.NoOwnStock; + FNotCheckStockFulfillmentForRecipes := Source.NotCheckStockFulfillmentForRecipes; + FParentProductId := Source.ParentProductId; + FPictureFileName := Source.PictureFileName; + FProductGroupId := Source.ProductGroupId; + FQuIdConsume := Source.QuIdConsume; + FQuIdPrice := Source.QuIdPrice; + FQuIdPurchase := Source.QuIdPurchase; + FQuIdStock := Source.QuIdStock; + FQuickConsumeAmount := Source.QuickConsumeAmount; + FQuickOpenAmount := Source.QuickOpenAmount; + FShoppingLocationId := Source.ShoppingLocationId; + FShouldNotBeFrozen := Source.ShouldNotBeFrozen; + FTreatOpenedAsOutOfStock := Source.TreatOpenedAsOutOfStock +end; + procedure TGrocyProduct.DefaultSetup(); begin FActive := '1'; diff --git a/library/kernel.application.pas b/library/kernel.application.pas index a7cb6d7..242b0ad 100644 --- a/library/kernel.application.pas +++ b/library/kernel.application.pas @@ -111,16 +111,25 @@ function TLidlToGrocy.InsertOFFImageInGrocy(OFFProductInfo: TOFFProductInfo): bo function TLidlToGrocy.GetGrocyProduct(LidlProduct: TItemsLine): TGrocyProduct; var GrocyProduct: TGrocyProduct; + + procedure InternalAddNewGrocyProduct; + begin + TLogger.Info('Not found!', []); + //In case of product doesn't exists in Grocy + GrocyProduct := AddNewGrocyProduct(LidlProduct); + end; + begin TLogger.Info('Find product in Grocy', []); GrocyProduct := nil; try GrocyProduct := FGrocyService.GetProductByBarcode(LidlProduct.CodeInput); - TLogger.Info('Found! Grocy Product ID = %d', [GrocyProduct.Id]); + if Assigned(GrocyProduct) then + TLogger.Info('Found! Grocy Product ID = %d', [GrocyProduct.Id]) + else + InternalAddNewGrocyProduct; except - TLogger.Info('Not found!', []); - //In case of product doesn't exists in Grocy - GrocyProduct := AddNewGrocyProduct(LidlProduct); + InternalAddNewGrocyProduct; end; Result := GrocyProduct; @@ -151,8 +160,10 @@ function TLidlToGrocy.AddNewGrocyProduct(LidlProduct: TItemsLine): TGrocyProduct if Assigned(GrocyProduct) then GrocyBarcode := FGrocyService.AddBarcodeToProduct(GrocyProduct.Id, LidlProduct.CodeInput); finally - OFFProductInfo.Free; - GrocyBarcode.Free; + if Assigned(OFFProductInfo) then + OFFProductInfo.Free; + if Assigned(GrocyBarcode) then + GrocyBarcode.Free; end; except on E: Exception do @@ -306,8 +317,6 @@ procedure TLidlToGrocy.DoRun; FConfiguration.SaveConfig; TLogger.InfoExit('Completed processing', []); - - Sleep(30000); end; Terminate; @@ -335,7 +344,7 @@ destructor TLidlToGrocy.Destroy; if Assigned(FLidlTickets) then begin - for I := 0 to length(FLidlTickets) - 1 do + for I := 0 to Length(FLidlTickets) - 1 do FLidlTickets[I].Free; SetLength(FLidlTickets, 0); end; diff --git a/service/grocy.service.pas b/service/grocy.service.pas index 1f630a6..8a9e5d8 100644 --- a/service/grocy.service.pas +++ b/service/grocy.service.pas @@ -5,7 +5,7 @@ interface uses - Classes, SysUtils, Grocy.Product, mormot.core.json, fphttpclient, base64, + Classes, SysUtils, Grocy.Product, mormot.core.json, fphttpclient, base64, ssockets, opensslsockets, mormot.core.os, mormot.core.Text, mormot.core.base, Grocy.Barcode, Grocy.ProductStock, OpenFoodFacts.ProductInfo, Kernel.Configuration; @@ -187,6 +187,8 @@ function TGrocyService.CreateProduct(OFFProductInfo: TOFFProductInfo): TGrocyPro end else if (FClient.ResponseStatusCode = 400) then begin + FreeRequestBody; + GrocyError := TGrocyError.Create; try LoadJson(GrocyError, Response, TypeInfo(TGrocyError)); @@ -194,17 +196,15 @@ function TGrocyService.CreateProduct(OFFProductInfo: TOFFProductInfo): TGrocyPro begin TLogger.Error('Failed to add a new product in Grocy due to violation of the uniqueness of the product name %s', [GrocyProduct.Name]); - FreeRequestBody; TLogger.Info('Finding Grocy product with same name "%s"', [GrocyProduct.Name]); Result := GetProductByName(GrocyProduct.Name); if Assigned(Result) then TLogger.Info('Found! Grocy Product ID = %d', [Result.Id]); - - // Now GrocyProduct doesn't need anymore - GrocyProduct.Free; - GrocyProduct := nil; end; + // Now GrocyProduct doesn't need anymore + GrocyProduct.Free; + GrocyProduct := nil; finally GrocyError.Free; end; @@ -230,7 +230,9 @@ function TGrocyService.AddBarcodeToProduct(const ProductId: integer; const Barco begin GrocyBarcode.Id := GetIdFromJsonGrocy(Response, 'created_object_id'); Result := GrocyBarcode; - end; + end + else + GrocyBarcode.Free; FreeRequestBody; end; @@ -243,7 +245,12 @@ function TGrocyService.GetProductByBarcode(Barcode: string): TGrocyProduct; Result := nil; try - Response := FClient.Get(Format(Self.BaseURL + UrlProductByBarcode, [Barcode])); + try + Response := FClient.Get(Format(Self.BaseURL + UrlProductByBarcode, [Barcode])); + except + on E: ESocketError do + TLogger.Exception(E); + end; finally if (FClient.ResponseStatusCode = 200) then Result := GetGrocyProductFromJson(Response); @@ -256,7 +263,12 @@ function TGrocyService.AddProductInStock(GrocyProductId: integer; ProductStock: try FClient.RequestBody := TRawByteStringStream.Create(ObjectToJson(ProductStock)); - FClient.Post(Format(Self.BaseURL + UrlAddProductStock, [GrocyProductId])); + try + FClient.Post(Format(Self.BaseURL + UrlAddProductStock, [GrocyProductId])); + except + on E: ESocketError do + TLogger.Exception(E); + end; finally Result := (FClient.ResponseStatusCode = 200); @@ -268,16 +280,31 @@ function TGrocyService.GetProductByName(Name: string): TGrocyProduct; var Response: string; GrocyProducts: TGrocyProductArray; + I: integer; begin Result := nil; + GrocyProducts := nil; try - Response := FClient.Get(Format(Self.BaseURL + UrlProductByName, [EncodeURLElement(Name)])); + try + Response := FClient.Get(Format(Self.BaseURL + UrlProductByName, [EncodeURLElement(Name)])); + except + on E: ESocketError do + TLogger.Exception(E); + end; finally if (FClient.ResponseStatusCode = 200) then begin DynArrayLoadJson(GrocyProducts, Response, TypeInfo(TGrocyProductArray)); + if Length(GrocyProducts) = 1 then - Result := GrocyProducts[0]; + Result := TGrocyProduct.Create(GrocyProducts[0]); + + if Assigned(GrocyProducts) then + begin + for I := 0 to Length(GrocyProducts) - 1 do + GrocyProducts[I].Free; + SetLength(GrocyProducts, 0); + end; end; end; end; @@ -294,7 +321,12 @@ function TGrocyService.ConsumeByBarcode(Barcode: string; Amount: integer): boole try FClient.RequestBody := TRawByteStringStream.Create(jObject.AsJSON); - FClient.Post(Format(Self.BaseURL + UrlConsumeByBarcode, [Barcode])); + try + FClient.Post(Format(Self.BaseURL + UrlConsumeByBarcode, [Barcode])); + except + on E: ESocketError do + TLogger.Exception(E); + end; finally Result := (FClient.ResponseStatusCode = 200); FreeRequestBody; @@ -311,7 +343,12 @@ function TGrocyService.UploadImageFile(ImageStream: TStream; FileName: string): FClient.AddHeader('Content-Type', 'application/octet-stream'); ImageStream.Position := 0; FClient.RequestBody := ImageStream; - FClient.Put(Format(Self.BaseURL + UrlUploadFile, [FileName])); + try + FClient.Put(Format(Self.BaseURL + UrlUploadFile, [FileName])); + except + on E: ESocketError do + TLogger.Exception(E); + end; finally Result := (FClient.ResponseStatusCode = 204); FClient.AddHeader('Content-Type', 'application/json');