Verificarea "in masa" (VerificaListaCIF ... 'MASA') pica pe ORA-01795 peste 1000 de coduri, iar esecul trimitea tot lotul la ANAF, cu pauze de o secunda la fiecare 100 de coduri. Pe langa asta, fiecare rand servit din cache era salvat inapoi in istoric si logat separat. - programe/validare.prg: CitesteIstoricPentruCoduri citeste pe transe de maxim 1000 de coduri legate cu OR in aceeasi interogare (fara obiecte noi in baza, compatibil cu Oracle 10g); plasa de siguranta cere codurile neacoperite o singura data, nu cod cu cod; SalveazaIstoricDinCursor sare peste randurile cu sursa CACHE*; bucla de log per rand devine o singura linie cu totalul. - clase/overificari.vc2: completarea tabelului de parteneri foloseste index pe codul normalizat si SEEK in loc de LOCATE cu UDF (era patratic). - utile/Teste/cache_anaf/: harness-uri de masurare si non-regresie pentru timpii de mai jos. Masurat pe MARIUSM_AUTO, cu ANAF blocat: 1000 de coduri 5,1 s -> 0,318 s; 1001 coduri 16,6 s cu ORA-01795 -> 0,553 s fara eroare; 3000 de coduri 1,565 s; 200 de coduri din cache 3,93 s -> 0,05 s, cu 0 randuri noi in istoric; completarea tabelului pentru 2000 de parteneri 11,97 s -> 0,028 s. Randurile intoarse si verdictele raman identice. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JCzVWfqscv1xyo5uvJiWiW
307 lines
11 KiB
Plaintext
307 lines
11 KiB
Plaintext
* test_timp_masa_peste1000.prg - continuarea masuratorii din test_timp_verificare_masa.prg:
|
|
* 1. curata randurile ramase in ISTORIC_CODURI_FISCALE peste watermark-ul rularii anterioare
|
|
* 2. costul unei scrieri goLog (STRTOFILE additive) in functie de marimea fisierului de log
|
|
* 3. costul unui apel CitesteIstoricPentruCoduri cu UN singur cod (plasa de siguranta)
|
|
* 4. rularea completa VerificaListaCIF pe un lot de peste 1000 de coduri (ANAF blocat),
|
|
* unde interogarea de cache pica pe ORA-01795 si se ajunge cod-cu-cod
|
|
*
|
|
* Rulare: vfp9.exe -A -T "...\test_timp_masa_peste1000.prg" [watermark]
|
|
|
|
LPARAMETERS tcWatermark
|
|
|
|
SET SAFETY OFF
|
|
SET TALK OFF
|
|
SET DELETED ON
|
|
SET EXACT ON
|
|
SET CENTURY ON
|
|
SET DATE DMY
|
|
SET NULLDISPLAY TO ''
|
|
CLOSE DATABASES
|
|
|
|
PUBLIC gcTestLog, gnApeluriANAF, gcMockUltimMesaj, gnMockUltimTip, gnMockRaspuns
|
|
gcTestLog = "D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\test_timp_masa_peste1000_log.txt"
|
|
STRTOFILE("START " + TTOC(DATETIME()) + CHR(13) + CHR(10), gcTestLog)
|
|
gnApeluriANAF = 0
|
|
gcMockUltimMesaj = ''
|
|
gnMockUltimTip = 0
|
|
gnMockRaspuns = 6
|
|
|
|
ON ERROR DO ErrP1000 WITH ERROR(), MESSAGE(), PROGRAM(), LINENO()
|
|
ON SHUTDOWN QUIT
|
|
|
|
DO D:\ROA\ROACONT\COMUN\utile\Teste\test_init_env_auto.prg WITH 'CENTRAL', 'MARIUSM_AUTO', 'ROMFASTSOFT'
|
|
IF gnHandle <= 0
|
|
DO WrLog2 WITH 'EROARE: conectare Oracle esuata - GATA'
|
|
QUIT
|
|
ENDIF
|
|
DO WrLog2 WITH 'mediu OK, schema=' + gcS
|
|
SET PROCEDURE TO "D:\ROA\ROACONT\COMUN\utile\Teste\mock_amessagebox.prg" ADDITIVE
|
|
|
|
* mock_amessagebox NU acopera apelurile de amessagebox facute din oproceduri_comune.prg
|
|
* (VFP rezolva intai in fisierul de proceduri curent), iar oexecutor.oExecuta deschide un
|
|
* formular modal la orice eroare SQL - headless asta blocheaza procesul. Deci inlocuiesc
|
|
* executorul cu o subclasa care nu deschide dialogul si numara erorile.
|
|
PUBLIC gnErorriSQL, gcUltimaEroareSQL
|
|
gnErorriSQL = 0
|
|
gcUltimaEroareSQL = ''
|
|
LOCAL loExecNou
|
|
loExecNou = CREATEOBJECT('oexec_fara_dialog')
|
|
loExecNou.nHandle = gnHandle
|
|
goExecutor = loExecNou
|
|
DO WrLog2 WITH 'executor inlocuit (fara dialog modal la eroare SQL)'
|
|
|
|
LOCAL lnWm, lcSql, lnT, lnI, lnRep
|
|
lnWm = IIF(TYPE('tcWatermark') = 'C' AND !EMPTY(tcWatermark), INT(VAL(tcWatermark)), 0)
|
|
|
|
*==========================================================
|
|
* 1. curatenie dupa rularea anterioara
|
|
*==========================================================
|
|
IF lnWm > 0
|
|
lcSql = 'SELECT COUNT(*) AS N FROM ISTORIC_CODURI_FISCALE WHERE ID > ' + TRANSFORM(lnWm)
|
|
IF goExecutor.oExecuta(lcSql, 'crsRest')
|
|
DO WrLog2 WITH 'randuri peste watermark ' + TRANSFORM(lnWm) + ': ' + TRANSFORM(crsRest.N)
|
|
USE IN (SELECT('crsRest'))
|
|
ENDIF
|
|
=goExecutor.oExecuta('DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ' + TRANSFORM(lnWm))
|
|
=goExecutor.oExecuta('COMMIT')
|
|
DO WrLog2 WITH 'curatenie facuta (ID > ' + TRANSFORM(lnWm) + ')'
|
|
ELSE
|
|
DO WrLog2 WITH 'fara watermark - nu sterg nimic'
|
|
ENDIF
|
|
|
|
PUBLIC gnIdMaxIstoric
|
|
gnIdMaxIstoric = 0
|
|
IF goExecutor.oExecuta('SELECT NVL(MAX(ID),0) AS IDMAX FROM ISTORIC_CODURI_FISCALE', 'crsWm2')
|
|
gnIdMaxIstoric = crsWm2.IDMAX
|
|
USE IN (SELECT('crsWm2'))
|
|
ENDIF
|
|
DO WrLog2 WITH 'watermark nou = ' + TRANSFORM(gnIdMaxIstoric)
|
|
|
|
*==========================================================
|
|
* 2. costul unei scrieri de log, in functie de marimea fisierului
|
|
*==========================================================
|
|
DO WrLog2 WITH ''
|
|
DO WrLog2 WITH '=== 2. cost STRTOFILE additive (asta face goLog.Log) ==='
|
|
LOCAL lcF, lcLinie
|
|
lcLinie = REPLICATE('x', 120) + CHR(13) + CHR(10)
|
|
lnRep = 300
|
|
|
|
lcF = 'D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\_probalog_mic.txt'
|
|
STRTOFILE('', lcF)
|
|
lnT = SECONDS()
|
|
FOR lnI = 1 TO lnRep
|
|
STRTOFILE(lcLinie, lcF, .T.)
|
|
ENDFOR
|
|
lnT = SECONDS() - lnT
|
|
DO WrLog2 WITH '2a fisier ~0 MB: ' + TRANSFORM(ROUND(lnT / lnRep * 1000, 2)) + ' ms/scriere (' + TRANSFORM(ROUND(lnT, 3)) + ' s / ' + TRANSFORM(lnRep) + ')'
|
|
|
|
lcF = 'D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\_probalog_mare.txt'
|
|
STRTOFILE(REPLICATE(lcLinie, 40000), lcF)
|
|
DO WrLog2 WITH ' fisier mare pregatit: ' + TRANSFORM(ROUND(FSIZE(lcF) / 1048576, 2)) + ' MB'
|
|
lnT = SECONDS()
|
|
FOR lnI = 1 TO lnRep
|
|
STRTOFILE(lcLinie, lcF, .T.)
|
|
ENDFOR
|
|
lnT = SECONDS() - lnT
|
|
DO WrLog2 WITH '2b fisier ' + TRANSFORM(ROUND(FSIZE(lcF) / 1048576, 2)) + ' MB: ' + TRANSFORM(ROUND(lnT / lnRep * 1000, 2)) + ' ms/scriere (' + TRANSFORM(ROUND(lnT, 3)) + ' s)'
|
|
|
|
* pentru comparatie: acelasi volum scris cu handle deschis o singura data
|
|
lcF = 'D:\ROA\ROACONT\COMUN\utile\Teste\cache_anaf\_probalog_handle.txt'
|
|
IF FILE(lcF)
|
|
ERASE (lcF)
|
|
ENDIF
|
|
LOCAL lnH
|
|
lnH = FCREATE(lcF)
|
|
lnT = SECONDS()
|
|
FOR lnI = 1 TO lnRep
|
|
=FPUTS(lnH, lcLinie)
|
|
ENDFOR
|
|
=FCLOSE(lnH)
|
|
lnT = SECONDS() - lnT
|
|
DO WrLog2 WITH '2c acelasi volum, handle deschis o data: ' + TRANSFORM(ROUND(lnT / lnRep * 1000, 3)) + ' ms/scriere'
|
|
|
|
*==========================================================
|
|
* 3. costul plasei de siguranta: o interogare per cod
|
|
*==========================================================
|
|
DO WrLog2 WITH ''
|
|
DO WrLog2 WITH '=== 3. CitesteIstoricPentruCoduri cu UN cod (plasa de siguranta) ==='
|
|
LOCAL loVer, lnZile
|
|
loVer = CREATEOBJECT('VerificareANAFTimp2')
|
|
lnZile = loVer.ZileCache()
|
|
|
|
lcSql = 'SELECT COD_FISCAL_N FROM (SELECT DISTINCT COD_FISCAL_N FROM ISTORIC_CODURI_FISCALE'
|
|
lcSql = lcSql + ' WHERE COD_FISCAL_N IS NOT NULL AND DATAORAV_ANAF IS NOT NULL'
|
|
lcSql = lcSql + ' AND SYSDATE - DATAORAV_ANAF <= ' + TRANSFORM(lnZile)
|
|
lcSql = lcSql + ' ORDER BY COD_FISCAL_N) WHERE ROWNUM <= 1200'
|
|
=goExecutor.oExecuta(lcSql, 'crsCod2')
|
|
|
|
IF USED('cLot')
|
|
USE IN cLot
|
|
ENDIF
|
|
CREATE CURSOR cLot (cod_fiscal C(30) NULL, data D NULL)
|
|
SELECT crsCod2
|
|
SCAN
|
|
INSERT INTO cLot (cod_fiscal, data) VALUES (ALLTRIM(TRANSFORM(crsCod2.COD_FISCAL_N)), DATE())
|
|
SELECT crsCod2
|
|
ENDSCAN
|
|
USE IN (SELECT('crsCod2'))
|
|
DO WrLog2 WITH 'coduri proaspete disponibile: ' + TRANSFORM(RECCOUNT('cLot'))
|
|
|
|
IF USED('crsUnul')
|
|
USE IN crsUnul
|
|
ENDIF
|
|
lnRep = MIN(100, RECCOUNT('cLot'))
|
|
lnT = SECONDS()
|
|
SELECT cLot
|
|
GO TOP
|
|
FOR lnI = 1 TO lnRep
|
|
=loVer.CitesteIstoricPentruCoduri(ALLTRIM(NVL(cLot.cod_fiscal, '')), DATE(), 'crsUnul', 'CACHE_INDISP')
|
|
SELECT cLot
|
|
SKIP
|
|
ENDFOR
|
|
lnT = SECONDS() - lnT
|
|
DO WrLog2 WITH '3a ' + TRANSFORM(lnRep) + ' apeluri cu un singur cod = ' + TRANSFORM(ROUND(lnT, 3)) + ' s'
|
|
DO WrLog2 WITH ' = ' + TRANSFORM(ROUND(lnT / lnRep * 1000, 2)) + ' ms/cod -> ' + TRANSFORM(ROUND(lnT / lnRep * 1000, 1)) + ' s la 1000 de coduri'
|
|
|
|
*==========================================================
|
|
* 4. flux complet peste limita de 1000
|
|
*==========================================================
|
|
DO WrLog2 WITH ''
|
|
DO WrLog2 WITH '=== 4. VerificaListaCIF pe lot > 1000 coduri (ANAF blocat) ==='
|
|
IF USED('cLot1001')
|
|
USE IN cLot1001
|
|
ENDIF
|
|
CREATE CURSOR cLot1001 (cod_fiscal C(30) NULL, data D NULL)
|
|
SELECT cLot
|
|
SCAN
|
|
INSERT INTO cLot1001 (cod_fiscal, data) VALUES (cLot.cod_fiscal, DATE())
|
|
SELECT cLot
|
|
ENDSCAN
|
|
FOR lnI = RECCOUNT('cLot1001') + 1 TO 1001
|
|
INSERT INTO cLot1001 (cod_fiscal, data) VALUES (ALLTRIM(STR(9000000 + lnI)), DATE())
|
|
ENDFOR
|
|
DO WrLog2 WITH 'lot = ' + TRANSFORM(RECCOUNT('cLot1001')) + ' coduri; START ' + TTOC(DATETIME())
|
|
gnApeluriANAF = 0
|
|
lnT = SECONDS()
|
|
=loVer.VerificaListaCIF('cLot1001', DATE(), 'crsRez1001', 'MASA')
|
|
lnT = SECONDS() - lnT
|
|
DO WrLog2 WITH ' erori SQL in flux: ' + TRANSFORM(gnErorriSQL) + ' [' + LEFT(gcUltimaEroareSQL, 90) + ']'
|
|
DO WrLog2 WITH '4a TOTAL = ' + TRANSFORM(ROUND(lnT, 3)) + ' s pentru ' + TRANSFORM(RECCOUNT('cLot1001')) + ' coduri'
|
|
DO WrLog2 WITH ' randuri intoarse: ' + TRANSFORM(IIF(USED('crsRez1001'), RECCOUNT('crsRez1001'), 0))
|
|
DO WrLog2 WITH ' apeluri ANAF (blocate): ' + TRANSFORM(gnApeluriANAF)
|
|
DO WrLog2 WITH ' ultim dialog interceptat: [' + LEFT(gcMockUltimMesaj, 100) + ']'
|
|
|
|
* acelasi lot, dar sub limita (1000 de coduri) - reper
|
|
IF USED('cLot1000')
|
|
USE IN cLot1000
|
|
ENDIF
|
|
CREATE CURSOR cLot1000 (cod_fiscal C(30) NULL, data D NULL)
|
|
SELECT cLot1001
|
|
GO TOP
|
|
FOR lnI = 1 TO 1000
|
|
INSERT INTO cLot1000 (cod_fiscal, data) VALUES (cLot1001.cod_fiscal, DATE())
|
|
SELECT cLot1001
|
|
SKIP
|
|
ENDFOR
|
|
DO WrLog2 WITH 'lot de reper = ' + TRANSFORM(RECCOUNT('cLot1000')) + ' coduri'
|
|
gnApeluriANAF = 0
|
|
lnT = SECONDS()
|
|
=loVer.VerificaListaCIF('cLot1000', DATE(), 'crsRez1000', 'MASA')
|
|
lnT = SECONDS() - lnT
|
|
DO WrLog2 WITH '4b TOTAL = ' + TRANSFORM(ROUND(lnT, 3)) + ' s pentru 1000 de coduri (sub limita IN)'
|
|
DO WrLog2 WITH ' randuri intoarse: ' + TRANSFORM(IIF(USED('crsRez1000'), RECCOUNT('crsRez1000'), 0))
|
|
DO WrLog2 WITH ' apeluri ANAF (blocate): ' + TRANSFORM(gnApeluriANAF)
|
|
|
|
*==========================================================
|
|
* 5. flux la 3000 de coduri (reale + sintetice) - dovada ca scaleaza peste 1000
|
|
*==========================================================
|
|
DO WrLog2 WITH ''
|
|
DO WrLog2 WITH '=== 5. VerificaListaCIF pe lot de 3000 coduri (ANAF blocat) ==='
|
|
IF USED('cLot3000')
|
|
USE IN cLot3000
|
|
ENDIF
|
|
CREATE CURSOR cLot3000 (cod_fiscal C(30) NULL, data D NULL)
|
|
SELECT cLot1001
|
|
GO TOP
|
|
SCAN
|
|
INSERT INTO cLot3000 (cod_fiscal, data) VALUES (cLot1001.cod_fiscal, DATE())
|
|
SELECT cLot1001
|
|
ENDSCAN
|
|
FOR lnI = RECCOUNT('cLot3000') + 1 TO 3000
|
|
INSERT INTO cLot3000 (cod_fiscal, data) VALUES (ALLTRIM(STR(9500000 + lnI)), DATE())
|
|
ENDFOR
|
|
DO WrLog2 WITH 'lot = ' + TRANSFORM(RECCOUNT('cLot3000')) + ' coduri; START ' + TTOC(DATETIME())
|
|
gnApeluriANAF = 0
|
|
gnErorriSQL = 0
|
|
lnT = SECONDS()
|
|
=loVer.VerificaListaCIF('cLot3000', DATE(), 'crsRez3000', 'MASA')
|
|
lnT = SECONDS() - lnT
|
|
DO WrLog2 WITH ' erori SQL in flux: ' + TRANSFORM(gnErorriSQL) + ' [' + LEFT(gcUltimaEroareSQL, 90) + ']'
|
|
DO WrLog2 WITH '5a TOTAL = ' + TRANSFORM(ROUND(lnT, 3)) + ' s pentru ' + TRANSFORM(RECCOUNT('cLot3000')) + ' coduri'
|
|
DO WrLog2 WITH ' randuri intoarse: ' + TRANSFORM(IIF(USED('crsRez3000'), RECCOUNT('crsRez3000'), 0))
|
|
DO WrLog2 WITH ' apeluri ANAF (blocate): ' + TRANSFORM(gnApeluriANAF)
|
|
|
|
*==========================================================
|
|
DO WrLog2 WITH ''
|
|
DO CurataP1000
|
|
DO WrLog2 WITH 'GATA ' + TTOC(DATETIME())
|
|
QUIT
|
|
|
|
|
|
PROCEDURE WrLog2
|
|
LPARAMETERS tcText
|
|
STRTOFILE(TRANSFORM(tcText) + CHR(13) + CHR(10), gcTestLog, .T.)
|
|
ENDPROC
|
|
|
|
PROCEDURE ErrP1000
|
|
LPARAMETERS tnError, tcMessage, tcProgram, tnLine
|
|
DO WrLog2 WITH 'EROARE ' + TRANSFORM(tnError) + ' [' + TRANSFORM(tcMessage) + '] in ' + ;
|
|
TRANSFORM(tcProgram) + ' linia ' + TRANSFORM(tnLine)
|
|
RETURN
|
|
ENDPROC
|
|
|
|
PROCEDURE CurataP1000
|
|
IF TYPE('gnIdMaxIstoric') <> 'N' OR gnIdMaxIstoric <= 0
|
|
DO WrLog2 WITH 'curatenie SARITA - watermark invalid'
|
|
RETURN
|
|
ENDIF
|
|
=goExecutor.oExecuta('DELETE FROM ISTORIC_CODURI_FISCALE WHERE ID > ' + TRANSFORM(gnIdMaxIstoric))
|
|
=goExecutor.oExecuta('COMMIT')
|
|
DO WrLog2 WITH 'curatenie: sterse randurile cu ID > ' + TRANSFORM(gnIdMaxIstoric)
|
|
ENDPROC
|
|
|
|
|
|
DEFINE CLASS oexec_fara_dialog AS oexecutor
|
|
|
|
FUNCTION oExecuta
|
|
LPARAMETERS tcSql, tcCursor, tlProgress, tcTitluProgress, tnHandle, tlShowError, tlQuitOnError, tlReconnect
|
|
LOCAL lcSql, lcCursor, lnHandle, lnRez
|
|
lcSql = IIF(EMPTY(tcSql), This.cSql, tcSql)
|
|
lcCursor = IIF(EMPTY(tcCursor), This.cCursor, tcCursor)
|
|
lnHandle = IIF(EMPTY(tnHandle), This.nHandle, tnHandle)
|
|
lnRez = This.oExecute(lcSql, lcCursor, tlProgress, tcTitluProgress, lnHandle)
|
|
IF lnRez < 1
|
|
gnErorriSQL = gnErorriSQL + 1
|
|
gcUltimaEroareSQL = TRANSFORM(This.cEroare)
|
|
ENDIF
|
|
RETURN (lnRez >= 1)
|
|
ENDFUNC
|
|
|
|
ENDDEFINE
|
|
|
|
|
|
DEFINE CLASS VerificareANAFTimp2 AS VerificareANAF
|
|
|
|
PROCEDURE OrdineCache
|
|
LPARAMETERS tcTraseu
|
|
RETURN 'CACHE,ANAF'
|
|
ENDPROC
|
|
|
|
PROCEDURE ANAF_SincronWebService_PlatitorTva
|
|
LPARAMETERS tcCursorListaCIF, tdData, tcAlias
|
|
gnApeluriANAF = gnApeluriANAF + 1
|
|
RETURN IIF(EMPTY(tcAlias), 'crsANAF', tcAlias)
|
|
ENDPROC
|
|
|
|
ENDDEFINE
|