Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

It's not the same without you

Join the community to find out what other Atlassian users are discussing, debating and creating.

Atlassian Community Hero Image Collage

Custom Script Listener Email Spam Upon Issue Update Edited

I'm running into a sporadic, not-testably-reproducible issue regarding a Custom Script Listener that updates an issue's due-date upon Priority change.  

For some issues, upon changing the priority, there seems to be an surge of Issue Update events that mirror the originally-triggering event and causes a huge amount of email spam (looking at the logs, the Custom Listener is being triggered every 5ms when this happens).  From the debug text in my script, when this occurs, the event where the priority was first change seems to continually get registered as a new event (they all show the same ChangeItems list referring to the initial change).

This doesn't always happen—in most cases, the custom listener updates the issue's due date without causing spam or triggering more events that trip off the same custom listener.  But when it does happen, it cause a huge CPU spike and floods our mail queue.

Since the custom listener is configured to trigger off of "Issue Update" events via the ScriptListener config, I'm assuming the following code (in particular, the last one where issueManager.updateissue is used) that updates the issueEvent with the updated dueDate somehow triggers an edge case that causes this bug to surface:


void updateIssueWithNewDueDate(Timestamp dueDate, IssueEventevent, String fieldName, StringBuffer debugText){
def issue = event.getIssue();
MutableIssue mutableIssue = (MutableIssue) issue;
if(!dueDate){
return
}else{
IssueManager issueManager = ComponentAccessor.getComponent(IssueManager.class)
mutableIssue.setDueDate(dueDate)
issueManager.updateIssue(event.getUser(), mutableIssue, EventDispatchOption.ISSUE_UPDATED, false)
}
}

 
Question: Should I be using a different method other than issueManager.updateissue(...) for persisting the due-date change to the issue?  Or is there some other bug underfoot here?(see: https://docs.atlassian.com/software/jira/docs/api/7.1.0-m01/com/atlassian/jira/issue/IssueManager.html#updateIssue-com.atlassian.jira.user.ApplicationUser-com.atlassian.jira.issue.MutableIssue-com.atlassian.jira.event.type.EventDispatchOption-boolean-) 

Here is the entire custom scriptRunner for more details.  A run down of the code:
The CustomListener is triggered against "Issue Updated" events on a project called SEC.  The script should update the due-date of the issiue when the priority of the issue changes (based off an irrelevant SLA calculation), but only for issues of type "Vulnerability":

import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.ComponentManager
import com.atlassian.jira.component.ComponentAccessor
import com.atlassian.jira.issue.CustomFieldManager
import com.atlassian.jira.issue.Issue
import com.atlassian.jira.event.issue.IssueEvent
import com.atlassian.jira.issue.MutableIssue
import com.atlassian.jira.issue.fields.CustomField
import com.atlassian.jira.model.ChangeItem
import com.atlassian.jira.issue.util.DefaultIssueChangeHolder
import com.atlassian.jira.issue.ModifiedValue
import com.atlassian.jira.issue.IssueManager
import com.atlassian.jira.event.type.EventDispatchOption

import java.sql.Timestamp
import java.util.HashMap
import java.util.Map

def String FIELD_PRIORITY = "priority"
def String FIELD_DUE_DATE = "Due Date"
def String ISSUE_TYPE = "Vulnerability"


def String PRIORITY_CRITICAL = "Critical";
def String PRIORITY_MAJOR = "Major";
def String PRIORITY_MEDIUM = "Medium";
def String PRIORITY_MINOR = "Minor";
def String PRIORITY_TRIVIAL = "Trivial";

def int SLA_DAYS_CRITICAL = 1;
def int SLA_DAYS_MAJOR = 7;
def int SLA_DAYS_MEDIUM = 30;
def int SLA_DAYS_MINOR = 120;
def int SLA_DAYS_TRIVIAL = 120;

boolean wasFieldChanged(IssueEvent event, String fieldName, String issueType, StringBuffer debugText) {
Issue issue = event.issue
String issueTypeName = issue.getIssueType().getName()
boolean isVulnerability = issueType.equals(issueTypeName)
addFieldToDebugText(debugText, "isVulnerability", String.valueOf(isVulnerability))
def changeItems = event?.getChangeLog()?.getRelated("ChildChangeItem")
addFieldToDebugText(debugText, "changeItems", changeItems.toString())
return isVulnerability && event?.getChangeLog()?.getRelated("ChildChangeItem")?.find{it.field == fieldName}
}

String getPriorityChangeValue(IssueEvent event){
event.issue.getPriority().name
}

Timestamp getCreateDateFromIssue(IssueEvent event){
Timestamp createDate = event.issue.getCreated();
return createDate;
}

Timestamp getDueDateFromPriority(String priority, Timestamp createDate, Map<String, Integer> priority2SLAMap){
Integer slaDays = priority2SLAMap.get(priority);
if(!slaDays){
return null
}
Calendar cal = Calendar.getInstance();
cal.setTime(createDate);
cal.add(Calendar.DAY_OF_WEEK, slaDays);
Timestamp dueDate = new Timestamp(cal.getTime().getTime());
return dueDate;
}

void updateIssueWithNewDueDate(Timestamp dueDate, IssueEventevent, String fieldName, StringBuffer debugText){
def issue = event.getIssue();
MutableIssue mutableIssue = (MutableIssue) issue;
if(!dueDate){
return
}else{
IssueManager issueManager = ComponentAccessor.getComponent(IssueManager.class)
mutableIssue.setDueDate(dueDate)
issueManager.updateIssue(event.getUser(), mutableIssue, EventDispatchOption.ISSUE_UPDATED, false)
}
}

void addFieldToDebugText(StringBuffer debugText, String fieldName, String fieldValue){
debugText <<= " " + fieldName + ": " + (fieldValue ?: "null") + " "
}

def Map<String, Integer> priority2SLAMap = new HashMap<String, Integer>();
priority2SLAMap.put(PRIORITY_CRITICAL, SLA_DAYS_CRITICAL);
priority2SLAMap.put(PRIORITY_MAJOR, SLA_DAYS_MAJOR);
priority2SLAMap.put(PRIORITY_MEDIUM, SLA_DAYS_MEDIUM);
priority2SLAMap.put(PRIORITY_MINOR, SLA_DAYS_MINOR);
priority2SLAMap.put(PRIORITY_TRIVIAL, SLA_DAYS_TRIVIAL);

def StringBuffer debugText = 'DEBUG TEXT: ' << " "
def wasPriorityChanged = wasFieldChanged(event, FIELD_PRIORITY, ISSUE_TYPE, debugText)
addFieldToDebugText(debugText, "Was priorty Changed", String.valueOf(wasPriorityChanged))
if (wasPriorityChanged) {
String priority = getPriorityChangeValue(event);
addFieldToDebugText(debugText, "priority", priority)
Timestamp createDate = getCreateDateFromIssue(event)
addFieldToDebugText(debugText, "Create Date", createDate.toString())
Timestamp dueDate = getDueDateFromPriority(priority, createDate, priority2SLAMap)
addFieldToDebugText(debugText, FIELD_DUE_DATE, dueDate.toString())
updateIssueWithNewDueDate(dueDate, event, FIELD_DUE_DATE, debugText);
}
log.warn(debugText) 

 

1 answer

Hi David,

My best guess would be that this line that updates the issue

   issueManager.updateIssue(event.getUser(), mutableIssue, EventDispatchOption.ISSUE_UPDATED, false)

is causing the listeners to be continually invoked because of the event that it dispatches. Your listener listens for the "Issue Updated" event - that's OK. However, when you set the due date and call updateIssue, you're firing another another "Issue Updated" event with the parameter: EventDispatchOption.ISSUE_UPDATED. That seems like it would again trigger the listener over and over and over.

Perhaps try dispatching no event when you update the issue?

   issueManager.updateIssue(event.getUser(), mutableIssue, EventDispatchOption.DO_NOT_DISPATCH, false)

https://docs.atlassian.com/software/jira/docs/api/7.10.0/com/atlassian/jira/event/type/EventDispatchOption.html#DO_NOT_DISPATCH

Good suggestion to use the DO_NOT_DISPATCH EventDispatchOption. I'll try that.  Thank you.

Hi David,

I know you said the problem was sporadic, though I would like to follow up to see if you've experienced the same problem within the last couple of days. Has the DO_NOT_DISPATCH EventDispatchOption seemed to make a difference?

Thanks,

Josh

Hi Josh,

I thought so at first, but unfortunately we are experiencing the same issue again, with watchers of tickets receiving hundreds of emails in succession after priority change.  Is there another approach to updating the issue programmatically here?  Perhaps a different method?  Or is there something else you could think would be causing this issue that I should be looking into?

 

Best,

 

David

Hi David,

Sorry to hear that it didn't work. Would you mind raising a support request with our dedicated support team? I think that they will be able to give your issue a deeper look. You can find the link to raise a support request through our portal here:

https://marketplace.atlassian.com/apps/6820/scriptrunner-for-jira?hosting=server&tab=support

You might want to include a link to this Community post when you raise the support request.

Thanks,

Josh

Suggest an answer

Log in or Sign up to answer
TAGS
Community showcase
Asked in Jira Service Desk

Calling all Insight users, we need your help!

Hello Insight users,  As part of our (Mindville's) acquisition by Atlassian, our training team is looking to build some new Insight training materials. It would really helpful if you can ...

55 views 0 0
View question

Community Events

Connect with like-minded Atlassian users at free events near you!

Find an event

Connect with like-minded Atlassian users at free events near you!

Unfortunately there are no Community Events near you at the moment.

Host an event

You're one step closer to meeting fellow Atlassian users at your local event. Learn more about Community Events

Events near you