10

I am using facebook-python-ads-sdk to make async calls for FB insights API as described.

params = {
    "time_increment": 1,
    "level": "ad",
    "date_preset": "last_28d",
    "breakdowns": "hourly_stats_aggregated_by_advertiser_time_zone",
    "limit": 1000
}

job = AdAccount("id").get_insights_async(params=params)
result_cursor = wait_for_async_job(job)
results = [item for item in result_cursor]

def wait_for_async_job(job):
    for _ in range(TIMEOUT):
        time.sleep(1)
        job = job.remote_read()
        status = job[AdReportRun.Field.async_status]
        if status == "Job Completed":
            return job.get_result()

So the job to retrieve insights for last_28d finishes in a few minutes, however, the pagination over the results can take up to an hour!

Is it the right way to paginate over an async job?

Community
  • 1
  • 1
Dejell
  • 13,947
  • 40
  • 146
  • 229

3 Answers3

10

I am posting the answer so it can help other developers that had the same issue.

modify:

return job.get_result()

to:

return job.get_result(params={"limit": 1000})

This will paginate over the results in jumps of 1000 and not the default which is 25.

The above change saved us 30 minutes of run.

Dejell
  • 13,947
  • 40
  • 146
  • 229
  • This actually helps for synchronous requests as well! I had an issue with `get_ad_sets()` caused by pagination. It took forever to complete, and most often than not I got `request limit reached`. Once I added 'limit': 1000 to `params`, the request ended after a few seconds! Thank you for that – Derorrist Aug 01 '18 at 10:22
0

Today I had the same problem and this code works for me

from facebook_business.adobjects.campaign import Campaign
from facebook_business.adobjects.adreportrun import AdReportRun
from facebook_business.adobjects.adsinsights import AdsInsights
import time

campaign = Campaign(<CAMPAIGN_ID>)

params = {
    'level': AdsInsights.Level.campaign,
}
async_job = campaign.get_insights(params=params, is_async=True)
async_job.api_get()
while while async_job[AdReportRun.Field.async_status]!= 'Job Completed':
     time.sleep(1)
     async_job.api_get()
time.sleep(1)
print(async_job.get_result())
  • Could you add some explanation to your code? That would increase the quality of your post. – Ruli Dec 11 '20 at 15:32
0

replace

return job.get_result(params={"limit": 1000})

with

list(async_job.get_result())

to get always all responses. get_result() is an iterator.

adamczarnecki
  • 16
  • 2
  • 6
  • 2
    This looks more like a comment to [the accepted answer](https://stackoverflow.com/a/45677205/2227743) rather than a new answer. – Eric Aya Aug 10 '21 at 09:46