Getting event first token with python client

Hello, I am using the python asana client, and I am able to work seamlessly with tasks :slight_smile:

However, I am trying to get events, and I encounter problems when trying to get the first token.

I have one task with uid : ‘12345’, and use the asana client as such :
client.events.get({‘resource’: ‘12345’, ‘sync’: None}, opt_pretty=True)
I would expect to get a 412 error, along somehow with the first token to pass to my next query.

How can I achieve that ?

Thanks !!

Here is the error message I get when I do :
next(client.events.get({‘resource’: ‘12345’, ‘sync’: None}, opt_pretty=True))

asana.error.InvalidTokenError: Sync token invalid or too old: Sync token invalid or too old. If you are attempting to keep resources in sync, you must fetch the full dataset for this query now and use the new sync token for the next sync.

The event Asana guy is definitely @Phil_Seeman, maybe he’ll be able to help!

2 Likes

Actually I work with webhooks, haven’t worked with Events per se.

@anon84267167, see if you can do something like the following but in Python:

1 Like

Hi @Phil_Seeman, thanks for the answer !
I actually already stumbled upon this issue, and :

  • What I am doing in Python is indeed the same thing as what’s done here in java : I try to get asana.client.events
  • The issue in the post ‘No Events firing by Asana’ is related to an internal issue at Asana (see [Matt_Bramlage]s answer) and was solved
  • The issue here is that events that were already tracked suddenly stop working

In my case, I was never able to track an event, because I cannot seem to understand how to get the first token to pass in the ‘sync’ parameter.

Basically my issue is the same as the one here

My issue is that in the error message, I only get :
asana.error.InvalidTokenError: Sync token invalid or too old: Sync token invalid or too old. If you are attempting to keep resources in sync, you must fetch the full dataset for this query now and use the new sync token for the next sync.

When I should also find the first sync token

Thanks for your help :smiley:

1 Like

More precisely :
with :
client.events.get({‘resource’: ‘12345’}, opt_pretty=True)
I get the error :
asana.error.InvalidTokenError: Sync token invalid or too old: Sync token invalid or too old. If you are attempting to keep resources in sync, you must fetch the full dataset for this query now and use the new sync token for the next sync.

And with next(asana.client.events.get_iterator({‘resource’: ‘12345’})),
I never get any answer, the console keeps executing and nothing happens for several minutes
Note that ‘12345’ is a simple task that was created this week, so very small history

@anon84267167,

While it seems unlikely to me, I wonder if the issue is that the python library is eating the sync token that’s getting returned because of the error, like was happening in the SO post you linked to, and thus never returning it to you.

Can you try the same call in Postman (or equivalent) and see if you get back a sync token in addition to the expected error return?

Hi,

I had this same issue and found this conversation.

Since I managed to get it working, I thought I would post how it works.

As @Phil_Seeman suggested, I also assumed the library was eating the sync token. But I managed to find it.

If I try this:

for event in client.events.get({‘resource’: ‘12345’, ‘sync’: None}, opt_pretty=True):
    print(event)

I get an asana.error.InvalidTokenError exception. What is printed on the screen is not very useful:

InvalidTokenError(‘Sync token invalid or too old: Sync token invalid or too old. If you are attempting to keep resources in sync, you must fetch the full dataset for this query now and use the new sync token for the next sync.’)

But I thought the only way for the library to give me the sync token, is via the exception object.

In fact, the exception object has a sync property with your token.

So, now, this is my code:

from asana.error import InvalidTokenError
def get_events_sync_token(client, task_id: str) -> str:
    try:
        list(client.events.get_events(
                {
                    "resource": task_id
                }
            ))
    except InvalidTokenError as e:
        return e.sync

def get_events_of_tasks(client, task_id: str):
    sync_token = get_events_sync_token(client, task_id)
    return client.events.get_events(
        {
            "resource": task_id,
            "sync": sync_token
        }
    )
1 Like

Since I posted here, I noticed the code in my previous post is wrong.

Events only get registered in a sync token after the token is created.

So, my function get_events_of_task was never going to respond any event. Simply because it generates a token and requests events with the same token immediately.

Here is a working version.

def get_events(
        client, resource_id: str, sync_token: Optional[str] = None
    ) -> Tuple[Iterable[dict], str]:
        params = {"resource": resource_id, "sync": sync_token}
        try:
            return client.events.get_next(params)
        except InvalidTokenError as e:
            return ([], e.sync)

This always gives a tuple with the events and the token to be used in the next call. That token needs to be stored somewhere and, next time you want to check for events, use the latest stored token.

3 Likes

There is a special place in heaven for people who come back to share solutions. And of course a place in hell for those saying “I found the solution, never mind” :sweat_smile:

1 Like

Thanks for the tip. one question, how do you stop the client to wait until an event occurs? if there’s no event for that token the function hangs there forever.

I ended up figuring out why the console hung infinitely: here is a thread where I explained my findings:

Hopefully this issue gets resolved.