Support set publish time on broker side - #3267
Conversation
Since apache#3155 there is a real need not to depend on client side clock for publish time field on message metadata. This change sets a default value for publish time field at client side in order to be able to be identified by broker easily and set newly calculated time on it. If time was normally set by the client on publish time, this update will be just ignored by broker. [pulsar-broker] - Read message metadata for produced messages in order to know whether the message was set onto default value and should be updated with time calculated by broker. - Add method to return previous metadata with publish time set by broker. [pulsar-client] - ProducerImpl client side set a default fixed size value for publish time. [pulsar-common] - Add modifyMessageMetadata method on Commands in order to update new modified fields on payload. The default constant value used to define the undefined number of milliseconds since epoch is going to be 13 decimal digits, the method currentTimeMillis will always return 13 decimal digits assuming the broker has the current time set correctly. So we are safe with the assumption that the return value is 13 decimal digits for more than the next two centuries.
27139bb to
05f2978
Compare
merlimat
left a comment
There was a problem hiding this comment.
Just leaving a couple of comments and considerations:
- The reason we're currently relying on the client specified publish time is that is "cheaper". In broker we don't have to re-serialize the protobuf metadata, but rather we pass the same unmodified buffer to BK client. In any case, I'd like to have the option to turn on/off this feature based on needs.
- Since there can be clock skew across brokers as well, we would also need to make sure that the timespace is always guaranteed to be monotonically increasing, in particular after a broker failover. (eg: after failover set publish-timestamp to be >= to the timestamp of last written message in the topic
- Right now, there is no option to set the publish timestamp (as opposed to the event time which is optional). Rather the publish timestamp is always automatically set in the client library. If we have the broker-set publish timestamp, we should always override what was passed by client. Another option, could be to leave the current publish-timestamp (or rename it, since that is fine in protobuf) and use a different field for the broker-set timestamp. When doing some operations (eg: TTL, delayed delivery, etc), we can use the broker-set timestamp if present or fallback to client-set otherwise.
- Continuing from the above point, we also need to consider this timestamp when doing async-replication. When the message is republished, it will need to have a new timestamp, to make sure the monotonicity is maintained.
| MessageMetadata msgMetadata = Commands.parseMessageMetadata(headersAndPayload); | ||
| headersAndPayload.resetReaderIndex(); | ||
|
|
||
| if (msgMetadata.getPublishTime() == Constants.PUBLISH_TIME_UNSET_MS) { |
There was a problem hiding this comment.
Instead of constants, we should just use the hasPublishTime() method that will report if the field was set in the serizalized protobuf binary.
There was a problem hiding this comment.
Sorry, I didn't explained why I did it that way.
The reason I used a constant of 13 digits size is because the method modifyMessageMetadata() should be able to just update this value without realloc the entire buffer due to being with different size, the problem with hasPublishTime() is that if it is false then publish time on metadata is literally '0' and the new epoch will be of 13 digits length.
The alternative approach I can think to get rid of the constant definition is to set publish time field on protobuf with the default value of 13 digits and testing if publish time has such default comparing with a new metadata created.
Maybe proto3 solved this? not really sure.
|
Thanks for your comments, I answer you each point:
|
1 similar comment
|
@sijie @merlimat I think this pr should be reviewed very carefully. IMHO #3155 could exist without this change, maybe with a warning to the user about publish time being client generated. Thanks! |
|
sorry for forgetting to follow up with your changes. IMO supporting setting publish time on broker is a great feature to have and would be very useful for many other use cases which require monotonically increasing "time". so I think the PR should not be considered just for #3155, it has a broader set of use cases to support. We should discuss this feature independent of #3155. I think general consensus of delayed message was using functions to achieve that. but we didn't have a consensus of #3155 (IMO it is a "delayed" subscription feature). I will ping the thread and let's come up with a consensus. IMO "delayed" subscription can be achieved with the proposal in #3155 /cc @merlimat |
|
@lovelle Just sent an email to that email thread to try to conclude the solution and get the community to achieve an agreement |
|
@sijie Excellent! fully agree with you! Thank you very much for the follow up 👍 |
Motivation
Since #3155 there is a real need not to depend on client side clock for publish time field on message metadata.
This change sets a default value for publish time field at client side in order to be able to be identified by broker easily and set newly calculated time on it. If time was normally set by the client on publish time, this update will be just ignored by broker.
Modifications
[pulsar-broker]
message was set onto default value and should be updated with time
calculated by broker.
[pulsar-client]
[pulsar-common]
fields on payload.
The default constant value used to set the undefined number of milliseconds since epoch is going to be 13 decimal digits, the method currentTimeMillis will always return 13 decimal digits assuming the broker has the current time set correctly.
So we are safe with the assumption that the return value is 13 decimal digits for more than the next two centuries.
Result
Any client which set publish time with default value will be updated by broker with current time.
TODO
Once this change is accepted: