-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Stream mailFolder messages along with '@odata.deltaLink' #44
Comments
Here's the documentation https://github.com/davidmoten/odata-client#delta-collections. CollectionPage<Message> delta = OdataFactory
.request()
.users('test@mydomain.com')
.mailFolders('inbox')
.messages()
.delta()
.get();
delta.stream()...
// a while later
delta = delta.nextDelta();
... |
BTW the first call to |
Is this question about serialization? If you serialize the |
Thanks for the response, Now we need to append 'deltaLink' with the last set of records(from the page containing deltaLink) to the agent. Can you please suggest how to fulfill this requirement? |
You can use the |
BTW in terms of page size you should also read https://github.com/davidmoten/odata-client#your-own-page-size. |
Thanks David for the consideration, Here we are using stream(as given below) and it seems that the library automatically serializes based on mail message records like collectionPage.currentPage();, since the data on agent doesn't shows the nextlink or deltalink. Any suggestions here?
|
Ah well this boils down to how a Stream serializes doesn't it. A Stream is not a List but it is like one for serialization purposes (the library you are using presumably does something predictable for Streams). Just imagine you take all the Message objects out of a CollectionPage object and add them to an ArrayList. What makes you think that the metadata will go across with it? It won't! What's the maximum number of messages you want to go across in one call to getMails? It certainly won't be 20 with your current code because the stream keeps getting more pages. You could just return BTW, you do realize that the Message object won't include email attachments, especially large ones, and there is weirdness with special attachments like Reference attachments? If you want to capture the whole SMTP message reliably you can get it in MIME format as a stream from Graph api using odata-client-msgraph. I can show you how if is of interest. |
Apologize, '.maxPageSize(20)' is not relevant in the function( 'GetMails') shared above, as the stream will automatically pull the the pages util deltalink is received. Agree we can pull all the records using 'nextPage().get()' until deltalink is received and finally add these records into a CustomPage along with deltalink. Using this approach the response on agent will have records as well as the deltalink. In this approach we need to store all the records into a list locally and if we consider a scenario where Mail-folder has millions of messages then this approach will impact the performance and also service may not be able to store all these messages locally, if it doesn't have enough memory. This is why we are going for stream but the only challenge using stream is how to send 'deltalink' in the response to the agent, so that next time agent can make request for only incremental changes. |
Thanks for the detail, I'll give you an example of what to do shortly. |
I'm adding a method with the signature Stream<ObjectOrDeltaLink<T>> streamWithDeltaLink() to The approach to solve your problem is to take a stream of n Message objects and convert that to a stream of n+1 wrapper objects where the first n objects contain a Message and the last object has an Optional deltaLink (after all, not every stream has a deltaLink at the end). When
I'll finish tests and then let you try it out. |
I've merged the change into master. So now you can do this: public Flux<ObjectOrDeltaLink<Message>> getMails()
{
Stream<ObjectOrDeltaLink<Message>> stream =
client
.users('test@mydomain.com')
.mailFolders('inbox')
.messages()
.delta()
.deltaTokenLatest()
.streamWithDeltaLink();
return Flux.fromStream(stream);
} Note the use of What library are you using to expose a Flux across the network (what library is doing the serialization of a Flux into JSON)? Is it WebFlux? |
Thank you David, yes we are using WebFlux. |
I'll look at a release in the next day or so. In the meantime you can just do this to use the SNAPSHOT version locally: git clone https://github.com/davidmoten/odata-client.git
cd odata-client
mvn clean install |
Hi David, Just small request can we have method 'streamWithDeltaLink' should be part of 'CollectionPageNonEntityRequest' and 'CollectionEntityRequestOptionsBuilder' also? Otherwise we are ok with the current code changes as well and below is the invocation:
|
Glad to hear it works @madanbisht, thanks for testing the change. I've added the extra methods as requested and I'll build a release shortly. |
0.1.35 is on Maven Central now. |
Thank you, now we are using build 0.1.35 and its perfectly working. Just one small request like deltalink, is it possible to add nextlink in the response as it will be useful to handle below failure scenario. Considering a scenario where mailbox has lets say 2 Million mails, using stream we will be able to pull all mails including deltalink(required for incremental messages). Adding nextlink in the response to the agent will enable the agent to initiate request only for remaining mails(which it doesn't received yet) using nextlink. |
Ha, getting complicated for you! To solve that problem I would call Are you trying to guarantee processing of every email? If so then I doubt using |
Hi David, The intent of our application is to retrieve mails from an account mailbox and store it somewhere in a disk, so that the mails can be restored back into the mailbox whenever required. Considering a scenario where an account is 5 to 10 years old, the account can have millions of messages and our application need pull all these messages. Once all mails for an account retrieved successfully, application will use deltalink to pull incremental mails in future. If the next pull(incremental) happens after 1 year from the last pull(very first pull) then again the account can have Millions of new mails. |
One more concern please correct, as you said that deltaToken has limited lifetimes then I think deltaLink will not be applicable after a week or month. |
There's not much out there but here's something that talks about delta links expiring: https://stackoverflow.com/questions/51933002/syncstatenotfound-error-how-to-fix-or-avoid and this says that they expire within 7 days: http://www.msfttoday.com/duration-of-change-tracking-tokens-for-identity-and-education-resources/ |
Thank you David for sharing it, it has an impact in our use case. Also your suggestions are appreciated on the above use case, i.e. error handling(due to connection error) for those scenario where application uses stream to process Millions of messages for an account(which is 5 to 10 years old) . |
Use raw SMTP format as I've already commented, not Message json. That way you retain everything about the email including all attachments no matter how big and the SMTP headers. You'll need to confirm the practicality of this for restoring an email to an account.
Solution for your error handling scenario is to pull more often to reduce the stream size and to account for expiry of deltaLink and handle duplicates sensibly. Handling of duplication is an inevitability, make sure you account for it. Microsoft suggests using a webhook for notification of changes so you don't have to poll for them. Worth looking at too. |
Thanks David for your kind support and understanding. Also we are interested on streamming SMTP message from Graph api using odata-client-msgraph. If required, we will create a new thread for it. |
Re SMTP MIME format, see https://github.com/davidmoten/odata-client#download-an-email-in-smtp-mime-format |
Hi David,
In our use case we are trying to stream all the messages from 'inbox' mailFolder(using delta()) to an agent application as shown below.
Here we are trying to append '@odata.deltaLink' in the final data to the agent, so that next time agent can use the '@odata.deltaLink' to get incremental changes in the mailFolder. Can you please help to fulfill this requirement using stream?
Thanks
Madan
The text was updated successfully, but these errors were encountered: