11package mServer .crawler .sender .arte .tasks ;
22
33import com .google .common .util .concurrent .RateLimiter ;
4+ import com .google .gson .Gson ;
5+ import de .mediathekview .mlib .Config ;
6+ import de .mediathekview .mlib .tool .Log ;
7+ import jakarta .ws .rs .client .Invocation .Builder ;
48import jakarta .ws .rs .client .WebTarget ;
9+ import jakarta .ws .rs .core .Response ;
10+ import mServer .crawler .FilmeSuchen ;
11+ import mServer .crawler .RunSender ;
512import mServer .crawler .sender .MediathekReader ;
613import mServer .crawler .sender .base .AbstractJsonRestTask ;
714import mServer .crawler .sender .base .CrawlerUrlDTO ;
815import mServer .tool .MserverDaten ;
916
1017import java .util .Optional ;
1118import java .util .concurrent .ConcurrentLinkedQueue ;
19+ import java .util .concurrent .TimeUnit ;
1220
1321public abstract class ArteRateLimitedJsonRestTask <T , R , D extends CrawlerUrlDTO > extends AbstractJsonRestTask <T , R , D > {
1422 private static final long serialVersionUID = 1L ;
1523 private static final RateLimiter rateLimiter = RateLimiter .create (MserverDaten .getArteRateLimit ());
16- private static final RateLimiter opaApirateLimiter = RateLimiter .create (1.0 );
24+ private static final RateLimiter opaApirateLimiter = RateLimiter .create (0.3 );
1725
1826 protected ArteRateLimitedJsonRestTask (MediathekReader aCrawler , ConcurrentLinkedQueue <D > urlToCrawlDTOs , Optional <String > authKey ) {
1927 super (aCrawler , urlToCrawlDTOs , authKey );
2028 }
2129
2230 @ Override
2331 protected void processRestTarget (final D aDTO , final WebTarget aTarget ) {
24- if (aTarget .getUri ().toString ().contains ("api.arte.tv/api/opa/" )) {
25- opaApirateLimiter .acquire ();
26- } else {
27- rateLimiter .acquire ();
32+ int retryCount = 0 ;
33+ int maxRetries = 3 ;
34+ boolean stop = false ;
35+
36+ while (!stop && !Config .getStop ()) {
37+ // Apply rate limiting before each request (including retries)
38+ if (aTarget .getUri ().toString ().contains ("api.arte.tv/api/opa/" )) {
39+ opaApirateLimiter .acquire ();
40+ } else {
41+ rateLimiter .acquire ();
42+ }
43+
44+ Builder request = aTarget .request ();
45+ final Optional <String > authKey = getAuthKey ();
46+ if (authKey .isPresent ()) {
47+ request = request .header (HEADER_AUTHORIZATION , authKey .get ());
48+ }
49+
50+ try (Response response = createResponse (request , aDTO )) {
51+ traceRequest (response .getLength ());
52+
53+ if (response .getStatus () == 200 ) {
54+ gsonBuilder .registerTypeAdapter (getType (), getParser (aDTO ));
55+ final Gson gson = gsonBuilder .create ();
56+ final String jsonOutput = response .readEntity (String .class );
57+ final R responseObj = gson .fromJson (jsonOutput , getType ());
58+ postProcessing (responseObj , aDTO );
59+ stop = true ;
60+ // Check if we got a 429 and have retries left
61+ } else if (response .getStatus () == 429 && retryCount < maxRetries ) {
62+ String retryAfter = response .getHeaderString ("Retry-After" );
63+ Log .sysLog ("429: " + aDTO .getUrl () + " - retry after: " + retryAfter );
64+ retryCount ++;
65+ try {
66+ TimeUnit .MILLISECONDS .sleep (60000 );
67+ } catch (InterruptedException ignored ) {
68+ }
69+ } else {
70+ FilmeSuchen .listeSenderLaufen .inc (crawler .getRunIdentifier (), RunSender .Count .FEHLER );
71+ FilmeSuchen .listeSenderLaufen .inc (crawler .getRunIdentifier (), RunSender .Count .FEHLVERSUCHE );
72+ handleHttpError (aDTO , aTarget .getUri (), response );
73+ stop = true ;
74+ }
75+ }
2876 }
29- super .processRestTarget (aDTO , aTarget );
3077 }
3178}
0 commit comments