igpapi — Instagram private API Simulator for Node.js (API reference) 4.14.0
    Preparing search index...

    Interface AndroidQuickPromotionStashState

    The app's quick-promotion stash: the moment each surface's last answered batch fetch came back. A slot whose surfaces all have a fresh answer resolves from the stash and sends no QuickPromotionSurfaceQueryV3; a surface without one — never asked, asked too long ago, or whose fetch failed — makes the slot fetch.

    451.0.0.53.80, decompiled: the QP SDK keeps one cache per (trigger, surface, trigger context) — QPSdkOnDemandSurfaceController builds a com.facebook.quickpromotion.sdk.fetcher.ondemand.OnDemandSurfaceTriggerCache per entry and asks the cache whether the fetch may be skipped (OnDemandSurfaceTriggerCache.A02, :563-588): a cache that has never been answered (A00 == 0), or a forced refresh, fetches; otherwise it is fresh while now <= answeredAtMs + ttl. The answer's time is stored whatever the answer carried (A01 = the answer's promotions, :532-534 — an answer with no promotion stores the empty list), and a failed fetch keeps the cache's previous time (jNow = onDemandSurfaceTriggerCache.A00, :332/:446), so a failure does not make the slot skip its next fetch. The app's own slot fetcher repeats the same window on its side (IGSlotFetcher's AnonymousClass0181: A02 = 2 h for a normal refresh, A01 = 10 s for a forced one).

    The time-to-live. OnDemandSurfaceTriggerCache.A02 picks it by the surface (:571-582): LOGIN_INTERSTITIAL takes C01Z9.A01 = TimeUnit.MINUTES.toMillis(30), BARCELONA_MEGAPHONE reads the MobileConfig parameter 36610524569411332 (seconds; its build default is C01Z9.A00), and every other surface takes C01Z9.A00 = TimeUnit.HOURS.toMillis(2) (C01Z9.java:9-10). The surfaces the library's slots ask about — the comment sheet's tooltip, megaphone, interstitial, promotional-dialog and floating-banner surfaces (media.comments.quick-promotion.ts), the Explore tab's six, the profile's four — are none of the two special ones, so their window is the two-hour constant; the MobileConfig parameter is not declared for them, because the app does not read a parameter for them.

    The app keys the cache by the fired trigger's surface with the trigger context, and the library's keys are the same pair (quickPromotionStashKey). A batch that names no context — the Explore tab's, the comment sheet's — has one key per surface, while the profile's names the profile it visits and the way it was reached, so two profiles are two answers (android-451/follow-from-search 026/040/054/071 fetch four of them in one process, android-451/media-like 108 fetches the one whose user had no fresh entry).

    The answer outlives the process, so a checkpoint carries it. The app persists the answer's time: the write path serialises the answer through OnDemandStashHelper.serialize (the promotions into the stash file, the time into the metadata store under lastFetchTime2/<stash key>), and OnDemandSurfaceTriggerCache.A01 (initializeFromStash) puts the stored time back into A00 when the next process builds the cache. So a restarted app opens the sheet without a batch while the answer is fresh, and the library's stash is carried by the checkpoint (the part android.quick-promotion-stash, encodeAndroidQuickPromotionStash / RestoreAndroidQuickPromotionStash): a restored process is as indistinguishable on the wire from a continued one as the app's own restart is. It is never written to the session snapshot: the snapshot is the account's identity, not one process's caches.

    interface AndroidQuickPromotionStashState {
        answeredAtMs: Map<string, number>;
    }
    Index

    Properties

    Properties

    answeredAtMs: Map<string, number>

    One entry per answered (trigger context, surface): the app's OnDemandSurfaceTriggerCache holds one cache per (trigger, surface, trigger context), so a surface answered for one profile is not answered for another. The key is quickPromotionStashKey; the value is when the answer came back (the process clock, milliseconds).