You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
subscription.pull() should return a list of objects rather than tuples. #913
Per the spec, each message in a multi-message pull response has its own ackId, but that ID is not part of the message object, which has its own messageId.
It is kind of like the difference between the "envelope From" and the "payload From: header" in SMTP. The "transfer agent" cares about the "envelope" ackId (because it must use it to acknowlege the message in order to prevent re-transmission), while the "normal" part of the application would care about the messageId.
Sure, so the idea then is... if we had a Message class, we could put the ackId into the instance, and even provide an acknowledge() method that handles this, right?
We do have a message class, but putting the acknowledge method on it would be wrong: it is much more closely tied in the API to the subscription (again, "envelope" vs. "payload").
The bits of the application that deal with the actual message payload are going to be very different from the part that does the pull + acknowlege part: the latter is likely to be "frameworky".
I think keeping the ackId out of the "payload" is actually a win.
Can you give any more background on why that's a win? If we put it in the message the list returns a list of Message objects. If we don't it's a list of tuples, that has more specific unpacking requirements.
So the code might look like:
formessageinsubscription.pull():
acknowledgement_system.acknowledge_receipt(message.ack_id)
# or even...acknowledgement_system.acknowledge_receipt(message)
message_processing_system.process_message(message)
In other words, I'm saying "I want to acknowledge the receipt of a message", treating the ackId as something that's part of the message. The "payload" is message.data... So a Message object is the envelope, and you can get the payload by looking at .data ..
In my mind the "payload" is the data, attrs, and messageId (analogous to headers and body of an SMTP message), while the "envelope" is the ackId.
I'm sorry that I don't seem to be communicating here my sense of the importance of separation of concerns, in addition to staying as close a reasonably possible to the concepts used by the back-end API:
The attributes of the current Message class all come from the PubsubMessage resource, and represent non-ephemeral data about the given message. They are the same whether the message is obtained via a pull() on a subscription, or via a push to an endpoint.
The ackId is part of the ReceivedMessage resource (along with the message, which is the PubsubMessage): it is only relevant for pull(): in push, the endpoint's HTTP response code acts as the acknowedgement.
Except in toy examples, the code dealing with pull() and acknowledge() will not care about the message object itself: it will dispatch it to other code which does care about the message, and then send the acknowlegement. The dispatched-to code which handles the message object itself won't care about the ackId at all.
OK, and if another attribute comes back with the ReceivedMessage (maybe an expiration or something of that nature) ? Will we continue unpacking tuples still?
It seems like if ReceivedMessage had more than just an ackId + PubsubMessage, we'd have wrapped it in an object. So my main point is...
It seems like it'd be nice if .pull() gets back a list of objects.
Those objects have ways to get the things you want from them
Envelope, aka ackId
Payload, aka PubsubMessage
Since the ackId is the only piece of data, and it has a 1-to-1 relationship with the PubsubMessage itself (I asked about this above), it seemed reasonable to put this together and say .pull() returns an object that let's you "get" the different things you want.
OK, and if another attribute comes back with the ReceivedMessage (maybe an expiration or something of that nature) ? Will we continue unpacking tuples still?
"We" don't unpack them -- the caller does. If it makes sense, we could bundle the two as a namedtuple, which would allow the caller to access the items so:
I've tried to share it above: the Message class we have now is a transport-neutral mapping of the PubsubMessage structure. Capturing the "pull-only" bits of ReceivedMessage in a separate class (or the namedtuple) maintains that clarity / separation of concerns.
Activity
dhermes commentedon Jun 6, 2015
message.get_data()when we can just saymessage.data?ack_idan optional attribute ofMessage?jgeewax commentedon Jun 6, 2015
I'm fine with just
.data.Can we ack multiple messages at a time? that is, could the following be possible in our current implementation?
tseaver commentedon Jun 9, 2015
Per the spec, each message in a multi-message
pullresponse has its ownackId, but that ID is not part of the message object, which has its ownmessageId.It is kind of like the difference between the "envelope From" and the "payload
From:header" in SMTP. The "transfer agent" cares about the "envelope"ackId(because it must use it to acknowlege the message in order to prevent re-transmission), while the "normal" part of the application would care about themessageId.jgeewax commentedon Jun 9, 2015
Sure, so the idea then is... if we had a
Messageclass, we could put theackIdinto the instance, and even provide anacknowledge()method that handles this, right?tseaver commentedon Jun 9, 2015
We do have a message class, but putting the
acknowledgemethod on it would be wrong: it is much more closely tied in the API to the subscription (again, "envelope" vs. "payload").jgeewax commentedon Jun 9, 2015
I get that it is logically a separate thing, however conceptually, the only thing I can acknowledge is a single message, right?
I'm OK with the acknowledge method living elsewhere, but wouldn't it make sense to put the
ackIdinto the message?tseaver commentedon Jun 9, 2015
The bits of the application that deal with the actual message payload are going to be very different from the part that does the
pull+acknowlegepart: the latter is likely to be "frameworky".I think keeping the
ackIdout of the "payload" is actually a win.jgeewax commentedon Jun 9, 2015
Can you give any more background on why that's a win? If we put it in the message the list returns a list of Message objects. If we don't it's a list of tuples, that has more specific unpacking requirements.
So the code might look like:
In other words, I'm saying "I want to acknowledge the receipt of a message", treating the
ackIdas something that's part of the message. The "payload" ismessage.data... So aMessageobject is the envelope, and you can get the payload by looking at.data..Is this crazy?
tseaver commentedon Jun 9, 2015
In my mind the "payload" is the
data,attrs, andmessageId(analogous to headers and body of an SMTP message), while the "envelope" is theackId.I'm sorry that I don't seem to be communicating here my sense of the importance of separation of concerns, in addition to staying as close a reasonably possible to the concepts used by the back-end API:
Messageclass all come from the PubsubMessage resource, and represent non-ephemeral data about the given message. They are the same whether the message is obtained via apull()on a subscription, or via apushto an endpoint.ackIdis part of the ReceivedMessage resource (along with themessage, which is thePubsubMessage): it is only relevant forpull(): inpush, the endpoint's HTTP response code acts as the acknowedgement.Except in toy examples, the code dealing with
pull()andacknowledge()will not care about the message object itself: it will dispatch it to other code which does care about the message, and then send the acknowlegement. The dispatched-to code which handles the message object itself won't care about theackIdat all.jgeewax commentedon Jun 9, 2015
OK, and if another attribute comes back with the
ReceivedMessage(maybe an expiration or something of that nature) ? Will we continue unpacking tuples still?It seems like if
ReceivedMessagehad more than just anackId+PubsubMessage, we'd have wrapped it in an object. So my main point is....pull()gets back a list of objects.ackIdPubsubMessageSince the
ackIdis the only piece of data, and it has a 1-to-1 relationship with thePubsubMessageitself (I asked about this above), it seemed reasonable to put this together and say.pull()returns an object that let's you "get" the different things you want.tseaver commentedon Jun 10, 2015
"We" don't unpack them -- the caller does. If it makes sense, we could bundle the two as a
namedtuple, which would allow the caller to access the items so:jgeewax commentedon Jun 10, 2015
I'd be fine with the named tuple, but then it leads to the question: why would we use a named tuple here instead of an object for
ReceivedMessage?Are we making the decision that "if there's only N properties and 0 methods, we should use a named tuple"?
jgeewax commentedon Jun 10, 2015
Also, using your example code, I'm a tiny bit confused why that's preferable to:
Is there some example you can share as to why that is a horrible idea ?
tseaver commentedon Jun 10, 2015
I've tried to share it above: the
Messageclass we have now is a transport-neutral mapping of thePubsubMessagestructure. Capturing the "pull-only" bits ofReceivedMessagein a separate class (or thenamedtuple) maintains that clarity / separation of concerns.jgeewax commentedon Jun 10, 2015
So what about the part asking about the named tuple vs object?
dhermes commentedon Dec 31, 2015
These discussion seems to have died. Closing out for now (feel free to re-open if feature is necessary)
Fixes for text encoding [(#913)](GoogleCloudPlatform/python-docs-samp…
fix: remove setup.cfg configuration for creating universal wheels (#913)
fix: remove setup.cfg configuration for creating universal wheels (#913)
chore(deps): update dependency google-api-core to v1.30.0 (#913)
chore(python): use python 3.10 for docs build (#913)
fix: Remove uses of six. #913 (#958)
chore(python): use python 3.10 for docs build (#913)
chore: drop 'setuptools' dependency (#913)
chore(deps): Update nox in .kokoro/requirements.in [autoapprove] (#913)