prebid / prebid-mobile-ios

Prebid Mobile SDK for iOS applications
Apache License 2.0
48 stars 93 forks source link

Timeout in bannerAdUnit.fetchDemand() when Prebid.shared.timeoutMillis value is equal to bannerAdUnit.setAutoRefreshMillis value #1028

Open RobertApikyan opened 4 months ago

RobertApikyan commented 4 months ago

Description

Starting from the second auto refresh update, the BannerAdUnit.fetchDemand() method completes with ResultCode.prebidDemandTimedOut code when the Prebid.shared.timeoutMillis value is equal to what has been set to bannerAdUnit.setAutoRefreshMillis().

To Reproduce Originally, this example is from the Prebid's iOS swift demo app (see GAMOriginalAPIDisplayBannerViewController) It is slightly modified, in the loadView() method the Prebid.shared.timeoutMillis = 30000 is added.

Important
  1. In the loadView() method set the Prebid.shared.timeoutMillis = 30000,
  2. Make sure the bannerAdUnit.setAutoRefreshMillis(time: 30000) is set to 30000 as well.

It is important to have 30000 set to Prebid.shared.timeoutMillis and to bannerAdUnit.setAutoRefreshMillis, because the issue reproduces only when both have the same value.

After running the sample, for the first time the bannerAdUnit.fetchDemand() completes with ResultCode.prebidDemandFetchSuccess and the ad loads, but for the subsequent auto refresh updates the bannerAdUnit.fetchDemand() fails with ResultCode.prebidDemandTimedOut and the ad fails to load.

In the logs
Prebid demand fetch for GAM Prebid demand fetch successful // This for the first time
Prebid demand fetch for GAM Prebid demand timedout
Prebid demand fetch for GAM Prebid demand timedout
Prebid demand fetch for GAM Prebid demand timedout 
...
Prebid demand fetch for GAM Prebid demand timedout
GAM did fail to receive ad with error: Error Domain=com.google.admob Code=1 "Request Error: No ad to show." UserInfo={NSLocalizedDescription=Request Error: No ad to show., gad_response_info=  ** Response Info **
    Response ID: (null)

  ** Loaded Adapter Response **
    (null)

  ** Extras Dictionary **
    {
    }

  ** Mediation line items **
}
The reproducible sample

Only Prebid.shared.timeoutMillis = 30000 is added to the loadView() method to the demo sample.

import UIKit
import PrebidMobile
import GoogleMobileAds

fileprivate let storedImpDisplayBanner = "prebid-demo-banner-320-50"
fileprivate let gamAdUnitDisplayBannerOriginal = "/21808260008/prebid_demo_app_original_api_banner"

class GAMOriginalAPIDisplayBannerViewController: BannerBaseViewController, GADBannerViewDelegate {

    // Prebid
    private var bannerAdUnit: BannerAdUnit!

    // GAM
    private var gamBanner: GAMBannerView!

    override func loadView() {
        super.loadView()
        // ** Set Prebid timeout = 30000
        Prebid.shared.timeoutMillis = 30000
        createAd()
    }

    func createAd() {
        // 1. Create a BannerAdUnit
        bannerAdUnit = BannerAdUnit(configId: storedImpDisplayBanner, size: adSize)
        bannerAdUnit.setAutoRefreshMillis(time: 30000)

        // 2. Configure banner parameters
        let parameters = BannerParameters()
        parameters.api = [Signals.Api.MRAID_2]
        bannerAdUnit.bannerParameters = parameters

        // 3. Create a GAMBannerView
        gamBanner = GAMBannerView(adSize: GADAdSizeFromCGSize(adSize))
        gamBanner.adUnitID = gamAdUnitDisplayBannerOriginal
        gamBanner.rootViewController = self
        gamBanner.delegate = self

        // Add GMA SDK banner view to the app UI
        bannerView?.addSubview(gamBanner)

        // 4. Make a bid request to Prebid Server
        let gamRequest = GAMRequest()
        bannerAdUnit.fetchDemand(adObject: gamRequest) { [weak self] resultCode in
            PrebidDemoLogger.shared.info("Prebid demand fetch for GAM \(resultCode.name())")

            // 5. Load GAM Ad
            self?.gamBanner.load(gamRequest)
        }
    }

    // MARK: - GADBannerViewDelegate

    func bannerViewDidReceiveAd(_ bannerView: GADBannerView) {
        AdViewUtils.findPrebidCreativeSize(bannerView, success: { size in
            guard let bannerView = bannerView as? GAMBannerView else { return }
            bannerView.resize(GADAdSizeFromCGSize(size))
        }, failure: { (error) in
            PrebidDemoLogger.shared.error("Error occuring during searching for Prebid creative size: \(error)")
        })
    }

    func bannerView(_ bannerView: GADBannerView, didFailToReceiveAdWithError error: Error) {
        PrebidDemoLogger.shared.error("GAM did fail to receive ad with error: \(error)")
    }
}

Expected behavior

The bannerAdUnit.fetchDemand() should not fail with ResultCode.prebidDemandTimedOut just because the Prebid.shared.timeoutMillis has the same value as bannerAdUnit.setAutoRefreshMillis.

Is this the expected behavior? Because this is happening only when both ResultCode.prebidDemandTimedOut and bannerAdUnit.setAutoRefreshMillis have the same value, when different values are set, it works well without failure for the auto refresh updates.

Thanks.

CC: @AbrahamArmasCordero