nezegettem, h milyen off-the-shelf megoldasok vannak retry logic-ra, amit mindenfele network operation-ok kore raknank. ezeket talaltam emlitesre meltonak: https://github.com/BrunoBonacci/safely https://github.com/joegallo/robert-bruce https://github.com/liwp/again https://github.com/grammarly/perseverance van nektek ebben tapasztalatotok? melyik megoldast ajanlanatok?
robert bruce-t használjuk egy-egy helyen, meg again-t. Most az utóbbival van kis viszketésem, mert csak exceptionre működik énnekem meg valami return value esetén is akarok retryolni, és kicsit drága csak ezért exceptionölni
talaltam amugy egy megoldast valamelyik railway-oriented-programming clojure lib-ben amivel tudsz olyan exceptiont csinalni ami nem capture-oli a stacktrace-t
ha!
de amugy nekunk is pont ez volt a fajdalmunk, h felesleges bonyolitas exception-oket bevonni a retry mechanizmusba.
viszont a callback az meg hasznos
lehet le kéne forkolnom, mert nem lenne bonya beadni valamit, ami retvalon is működik
https://github.com/fmnoise/flow/blob/1e618e30fb683999662f0b17e1b8590982867d3b/src/fmnoise/flow/Fail.java#L22-L23
setting that writableStackTrace parameter of the RuntimeException protected constructor to false is what prevents generation of the stack trace.
this Fail class makes a public visibility constructor, to allow controlling the writableStackTrace parameter.
btw, the interpretation of the writableStackTrace is defined all the way down in java.lang.Throwable, so technically u can even extend that.
https://github.com/openjdk/jdk/blob/4a20691e9b0276e2dc5e7eb6a4d05393d6b4c99c/src/java.base/share/classes/java/lang/Throwable.java#L379-L394
zsír, köszi!
most latom csak h angolul irtam :) rossz uzemmodban maradt az agyam :)
jo lenne atirni ezt a Fail class-t clojure-be, de annyira nem vagyok profi interop meg :gen-class téren még h pikk pakk meg birjam csinálni.
csak ezert az egy class kedveert meg nem akarom a build process-t javac-vel bonyolítani....
@imre te vagod h h kene?
Hehe, én is ilyeneken gondolkodtam. gen-class elvileg működhet, de annak is kell egy precompile step, ha jól tudom, see docs + https://clojure.org/guides/deps_and_cli#prep_libs
Én végül fogtam és berántottam a flow libet cakkumpakk, nem nagy méret és a mvn artifactba már bele van forgatva 🙂
(do
(require 'criterium.core)
(criterium.core/with-progress-reporting
(criterium.core/quick-bench
(try
(throw (ex-info "Fail" {:operation "foo"}))
(catch Exception e
(assert (ex-data e))))
)))
(do
(require 'criterium.core)
(require 'fmnoise.flow)
(criterium.core/with-progress-reporting
(criterium.core/quick-bench
(try
(fmnoise.flow/fail-with {:msg "Fail" :data {:operation "foo"}})
(catch Exception e
(assert (ex-data e))))
)))
11us vs 37ns
jelentős
így talán mégis megmaradhat az again
mekkora nemmindegy, kicsi biorobot vagy nagy? :) a ti esetetekben amugy elofordul olyan suruseggel a retry, h szamitson ez a 11 microsec? alex miller is ezt kerdezte annak a jira ticketnek a kapcsan, ami felvetette h tamogassa az ex-info a stack trace nelkuli exception keszitest, de nem jott valasz ra
en amugy nem a teljesitmeny miatt neztem ennek utana, hanem azert mert bosszantott h mikor kiprinteltem egy ilyen exceptiont ami retry-ra van hasznalva, akkor a stack trace teleokádta a kepernyot es a lenyegi adat nem latszott...
de most hogy igy mondom... lehet azt kene csinalni, h legyartasz egy ex-info peldanyt egyszer, kifejezetten olyan celra h retry-t triggerelj es azon meghivod a .clearStackTrace-t es az application code-bol mindig ugyanezt az egy ex-info peldanyt throw-olod
tehat gyakorlatilag sentinel value-kent kezeled.
(ns lab)
(def empty-stack-trace
(make-array StackTraceElement 0))
(defn clear-stack-trace! [^Throwable t]
(doto t (.setStackTrace empty-stack-trace)))
(def retry-ex
(-> "Retry" (ex-info {:asd 123}) clear-stack-trace!))
(comment
(-> retry-ex throw)
(-> *e)
(-> *e clojure.repl/pst)
)az se egy rossz ötlet
bár https://stackoverflow.com/questions/49534361/throw-same-exception-instance-multiple-times
Nem láttam meggyőző érvet a SO cikkben ami ellent mondana ennek a use-case-nek, bar azt nem tudom hogy mi az a TargetSite amiről beszélnek.
De az tény hogy nem próbáltam hogy másik thread-ből dobva mi történik.
hu de jo h megtaláltam ezt a threadet
bár ahogy nézem egyik se tökéletes
semmi se tokeletes... 🙂 meselj majd h mire jutottal veluk!
nekem altalanos http client retry megoldas kene. 1. probaltam egy https://github.com/oliyh/martian interceptor-kent implementalni a retry-t, de azzal az a baaaj, h ha legutolso interceptor-nak rakom be, akkor a ring-like request body-t nem tudom masodjara kikuldeni, ha egy stream volt es nem byte-array v string. 2. elofordulhat h a retry korok soran az oauth access token lejar es akkor kell egy token refresh-t vegeznem es az ismetlendo request-ben az uj tokent kell hasznalnom, valamit az uj access tokent (meg esetleg refresh tokent) le kell mentsem adatbazisba is, tehat a http kliensnek hozza kell tudni a ferni ezekhez a rendszerekhez is es az interceptor-ok egy reszet legalabb ujra kell futtatni h friss credential-okkal probalodjon ujra a request
mi ennek egy valtozatat hasznaljuk: https://github.com/Datomic/ion-starter/blob/master/src/datomic/ion/starter/utils.clj#L4-L34 de ez csak Datomic Cloud-hoz egy peldakent lett osszedobva es nincs hozza teszt, meg exception dobalasaval jelzi a muvelet, h szukseg van retry-ra, ahelyett h csak egy anomaly-t adna vissza. 0 observability, h hanyszor lett valami ujra probalva. szal nagyon minimal es nagyon bespoke megoldas.