Replies: 6 comments
-
Also, here is a code checking the same broken behavior for users.threads.list: Codeasync test2() {
console.log(
"Performing test if 'users.threads.list' returns threads sorted by decreasing dates and historyIDs of their first messages.",
)
const count = 100
const cfg: GmailApi.Params$Resource$Users$Threads$List = {
userId: 'me',
maxResults: count,
}
const resp = await Auth.catchAllOAuth(() => this.api.users.threads.list(cfg))
if (resp.isErr()) {
console.error('GMail API query error.', resp.error)
return
}
const list = resp.value.data.threads
if (list == null) {
console.error('GMail API invalid response.')
return
}
let isHistoryIdDecreasing = true
let isDateDecreasing = true
let prevHistoryId: null | number = null
let prevDate: null | number = null
let i = 0
for (const thread of list) {
i++
const id = thread.id
if (id == null) {
console.error('Thread is missing the "id" field.')
return
}
const threadQuery = {userId: 'me', id}
const threadResp = await Auth.catchAllOAuth(() => this.api.users.threads.get(threadQuery))
if (threadResp.isErr()) {
console.error('GMail API query error.', threadResp.error)
return
}
if (threadResp.value.data.messages == null) {
console.error('Thread is missing the "messages" field.')
return
}
const firstMessage = threadResp.value.data.messages[0]
if (firstMessage == null) {
console.error('Thread is missing the first message.')
return
}
const historyIdStr = firstMessage.historyId
const dateStr = firstMessage.internalDate
if (!historyIdStr || !dateStr) {
console.error('First message is missing the "historyId" or "internalDate" field.')
return
}
const historyId = parseInt(historyIdStr, 10)
const date = parseInt(dateStr, 10)
let localIsHistoryIdDecreasing = true
let localIsDateDecreasing = true
if (prevHistoryId != null && prevHistoryId < historyId) {
isHistoryIdDecreasing = false
localIsHistoryIdDecreasing = false
}
if (prevDate != null && prevDate < date) {
isDateDecreasing = false
localIsDateDecreasing = false
}
prevHistoryId = historyId
prevDate = date
console.log(
`${i}/${count}: historyId: ${historyId}, date: ${date}, isHistoryIdDecreasing: ${localIsHistoryIdDecreasing}, isDateDecreasing: ${localIsDateDecreasing}`,
)
}
console.log({isHistoryIdDecreasing, isDateDecreasing})
} Output:
|
Beta Was this translation helpful? Give feedback.
-
Also, to make it more visual, I plotted the time I get from ![]() And here is plot of ![]() |
Beta Was this translation helpful? Give feedback.
-
What is even worse, it appears that Codeasync test_invariants_history_list() {
console.log(
"Performing test if 'users.history.list' returns history records sorted by increasing update date.",
)
const viz = (t: boolean) => (t ? '✅' : '❌')
const count = 100
const cfg: GmailApi.Params$Resource$Users$Messages$List = {
userId: 'me',
maxResults: count,
}
const resp = await Auth.catchAllOAuth(() => this.api.users.messages.list(cfg))
if (resp.isErr()) {
console.error('GMail API query error.', resp.error)
return
}
const list = resp.value.data.messages
if (list == null) {
console.error('GMail API invalid response.')
return
}
const lastMessage = list[list.length - 1]
if (lastMessage == null) {
console.error('Last message is missing.')
return
}
const lastMessageId = lastMessage.id
if (lastMessageId == null) {
console.error('Last message is missing the "id" field.')
return
}
const lastMessageQuery = {userId: 'me', id: lastMessageId}
const lastMessageResp = await Auth.catchAllOAuth(() =>
this.api.users.messages.get(lastMessageQuery),
)
if (lastMessageResp.isErr()) {
console.error('GMail API query error.', lastMessageResp.error)
return
}
const startHistoryId = lastMessageResp.value.data.historyId
if (startHistoryId == null) {
console.error('Last message is missing the "historyId" field.')
return
}
const historyCfg: GmailApi.Params$Resource$Users$History$List = {
userId: 'me',
startHistoryId,
maxResults: 500,
}
const historyResp = await Auth.catchAllOAuth(() => this.api.users.history.list(historyCfg))
if (historyResp.isErr()) {
console.error('GMail API query error.', historyResp.error)
return
}
const historyList = historyResp.value.data.history
if (historyList == null) {
console.error('GMail API invalid response.')
return
}
let localDateIncreasing = true
let prevDate: null | number = null
const updateCount = historyList.length
let i = 0
for (const update of historyList) {
i++
if (update.messages == null) {
console.error('Update is missing the "messages" field.')
return
}
let m = 0
for (const message of update.messages) {
m++
if (message.id == null) {
console.error('Message is missing the "id" field.')
return
}
const messageQuery = {userId: 'me', id: message.id}
const messageResp = await Auth.catchAllOAuth(() =>
this.api.users.messages.get(messageQuery),
)
if (messageResp.isErr()) {
console.error('GMail API query error.', messageResp.error)
continue
}
const dateStr = messageResp.value.data.internalDate
if (!dateStr) {
console.error('Message is missing the "internalDate" field.')
return
}
const date = parseInt(dateStr, 10)
if (prevDate != null && prevDate > date) {
localDateIncreasing = false
} else {
localDateIncreasing = true
}
prevDate = date
console.log(
`${i}/${updateCount}[${m}]: date: ${date}, dateIncreasing: ${viz(localDateIncreasing)}`,
)
}
}
} Output
|
Beta Was this translation helpful? Give feedback.
-
Moreover, as you can see in the above test, |
Beta Was this translation helpful? Give feedback.
-
I also got the same case, and my sync process was broken due to these inconvenients. |
Beta Was this translation helpful? Give feedback.
-
Hi there! Thanks for the writeup @wdanilo! As you mentioned this is likely an API issue. As this is mostly a generated library unfortunately we don't have much pull to help. I'll convert this to a discussion so people can follow along! |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Description
users.messages.list returns messages in a little bit random order.
I also reported the issue here, but knowing Google's issue tracker, I will get a sensible reply there in a few years, so trying my luck here as well :(
Code
I'm using the following code:
Output
Summary
As you can see, the message internalDate is sometimes ... increasing. I've observed the same behavior for users.threads.list. In such a scenario:
What is described here: https://developers.google.com/gmail/api/guides/sync is not true, I can't query for the first message of users.messages.list, remember its historyId and assume this is the newest historyId, as this might NOT be the newest message.
What is described here: https://developers.google.com/gmail/api/reference/rest/v1/users.history/list (
History IDs increase chronologically but are not contiguous with random gaps in between valid IDs
) is not true, as you can see, historyIDs are sometimes increasing for older messages.Beta Was this translation helpful? Give feedback.
All reactions