zenpy icon indicating copy to clipboard operation
zenpy copied to clipboard

'async' on ticket creation does not return id of the ticket

Open Gera3dartist opened this issue 1 year ago • 5 comments

There is a doc describing response and it states:

The response includes the new ticket id

Current observation, is that zenpy does not include id of the ticket, Expectation is: zenpy response for async ticket creation is consistent with underlying zendesk API

For reproduce I've been trying this example:

>>> from zenpy import Zenpy
>>> from zenpy.lib.api_objects import  Ticket, Comment
>>> data = {"email": "<email",
"token": "<token>",
"subdomain": "<domain",}

>>> client = Zenpy(**data)
>>> result = client.tickets.create(Ticket(
...   requester_id=123,
...   brand_id=123,
...   subject='subject of the ticket',
...   status='pending',
...   ticket_type='problem',
...   priority='urgent',
...   comment=Comment(html_body='some comment')
... ), **{'async': True})
>>> result.to_dict()
{'id': 'V3-796af36f0956fe622f95b126aca2d123', 'message': None, 'progress': None, 'results': None, 'status': 'queued', 'total': 1, 'url': 'https://<subdomain>.zendesk.com/api/v2/job_statuses/V3-796af36f0956fe622f95b126aca2123f.json'}

[Kind of Workaround] the ticket ID can be retrieved, eventually with consequent call to fetch job result:

>>> client.job_status(id=result.id).results
[JobStatusResult(id=<ticket_id>)]

On the other hand, same call with requests.Session returns ticket id immediately:

>>> ticket_payload = {
...     'ticket': {
...         'subject': 'New Support Request',
...         'comment': 'This is the description of the support request.',
...         'priority': 'normal'
...     }
... }
>>> 
>>> r = session.post('https://<subdomain>.zendesk.com/api/v2/tickets.json?async=true', json=ticket_payload)
>>> r
<Response [202]>
>>> r.json()
{'ticket': {'id': 7768}, 'job_status': {'id': 'V3-dccc52227f1b2e92265e628d99cc8123', 'url': 'https://subdom.zendesk.com/api/v2/job_statuses/V3-dccc52227f1b2e92265e628d99cc8123.json', 'total': 1, 'progress': None, 'status': 'queued', 'message': None, 'results': None}}

Gera3dartist avatar Aug 23 '23 15:08 Gera3dartist

The crux of the problem is how Zenpy handles a response. It usually expects a single object or a collection of similar objects. In this case, we get two different objects - a job status and a ticket. So Zenpy takes a first thing it knows, the job status, and discards everything else.

Fixing this doesn't seem easy.

Ptr314 avatar Aug 23 '23 16:08 Ptr314

@Ptr314 Would the extension of zenpy.lib.api.BaseApi._response_handlers with one more handler specifically to handle asynchronous response improve the state of affairs?

akalex avatar Aug 24 '23 05:08 akalex

@akalex usually Zenpy returns an object or a generator. Some analysis is expected if it can return two different objects.

Ptr314 avatar Aug 24 '23 08:08 Ptr314

@Ptr314 that's what I meant. New objects can be introduced to cover this case. However, I am not an expert and may not know the whole complexity of the implementation. So, I have full confidence in your expertise.

akalex avatar Aug 25 '23 09:08 akalex

Will this issue be considered soon?

akalex avatar Sep 20 '23 11:09 akalex

I see the inefficiency here..... But I'm not 100% sure of what to do with it just yet :) The fact of the matter is, you CAN get the ticket_id with discovery from the job key.

Honestly, a true async job system that is leaking the primary key of any record that is created or pre-created for you is leaking that it did work. I hate to say it, but I may not be a fan of that implementation leak, or even the use of it, or even that style.

The job system is the authoritative source of truth at that point you ask for any async activity to be done. And that's where you should get any further data from.

Let's consider a failure scenario:

  1. you ask for async ticket create but you DO have the ticket id
  2. full, formal ticket create fails
  3. you don't check the job system but keep polling for that ticket id instead of the job id (maybe the ticket goes away 404 if commit failure occurs????)

See where I'm going here? In both cases of success and failure, the job system is and should be the (graceful) source of truth.

So because of that I'm leaning towards the job system being the source of truth and main object here.

Disclosure: I am not a systems architect or an API expert.

cryptomail avatar May 12 '24 15:05 cryptomail