Answer by Ezequiel Consorti on 08 November 2022
Hi Antje,
Thanks for reaching out to us with your question!
While I understand you would expect to have the same description in all 3 issues, please note that the reason why you ended up with a different description in one of the issues is because the updates were done almost simultaneously.
In your scenario the Issue description was modified first in B_JSM (Descriptio .A) and then almost simultaneously in A_JSO (Description.B)
- D.A gets synced from B_JSM to A_JSM while D.B is posted in A_JSO (At this point you have B_JSM w/ D.A (original) A_JSM w/ D.A (sync1) A_JSO w/ D.B (original))
- A_JSM updates A_JSO sharing D.A while at the same time A_JSO updates A_JSM sharing D.B (B_JSM w/ D.A (original) A_JSM w/ D.B (sync2) A_JSO w/ D.B (sync1))
- A_JSM was updated a second time and syncs the update with B_JSM (B_JSM w/ D.B (sync1) A_JSM w/ D.B (sync2) A_JSO w/ D.B (sync1))
A way to avoid this is to implement a rule in your scripts that checks the timestamp on each update and only syncs the description coming from the remote side if it is older than the current description in the destination.
In the following community post with a similar scenario Avoid updating issue with older changes ADO <> Jira, Jira <> Jira, ServiceNow <> Jira (old community), you can find a video explaining how this script works and a detailed explanation on the whole logic behind it.
While I will be sharing the scripts directly in this post, I highly encourage you to review the shared one to have a better understanding on the subject.
// Outgoing Sync Rules
// Avoid updating issue with older changes Jira <> Jira
replica.changeHistory = issue.changeHistory
// Incoming Sync Rules
// Avoid updating issue with older changes Jira <> Jira
def fieldToLastUpdateDateFn = { exalateUserKey -> { history ->
history
.sort { c -> c.created.time }
.reverse()
.findAll { c ->
c.author.key != exalateUserKey
}
.inject([:]) { result, c ->
c.changeItems.inject(result) { r, i ->
String k = i.field
if (r[k] == null) {
r[k] = c.created
}
r
}
}
}}
if (firstSync) {
issue.summary = replica.summary
issue.description = replica.description
} else {
def HOUR = 1000 * 60 * 60
def THREE_HOURS = 3 * HOUR
def remoteFieldToLastUpdateDate = fieldToLastUpdateDateFn("exalate")(replica.changeHistory)
remoteFieldToLastUpdateDate = remoteFieldToLastUpdateDate.inject([:]) { r, k, v ->
r[k] = new Date((v + THREE_HOURS) as Long)
r
}
def localFieldToLastUpdateDate = fieldToLastUpdateDateFn("exalate")(issue.changeHistory)
if (remoteFieldToLastUpdateDate."description" > localFieldToLastUpdateDate."description") {
issue.description = replica.description
}
if (remoteFieldToLastUpdateDate."summary" > localFieldToLastUpdateDate."summary") {
issue.summary = replica.summary
}
if (remoteFieldToLastUpdateDate."Severity" > localFieldToLastUpdateDate."Severity") { issue.Severity = replica.Severity
}
}
By implementing this script in your scenario A_JSO shouldn’t be updated with the description coming from B_JSM as D.B is older than D.A leaving all 3 issues with the same description (D.B).
Please note that the shared script implements the timestamp rule for description and summary, you can include or exclude more fields from this rule by adding additional if() or removing an existing one.
I hope you find this information useful!
Regards,
Ezequiel