-
Bug
-
Resolution: Unresolved
-
Medium
-
None
-
9.12.0, 10.3.0, 10.3.12, 11.0.0, 11.1.1
-
None
-
9.12
-
Severity 2 - Major
-
Issue Summary
When Jira serializes issue payloads for webhooks, the process of including changelog items suffers from an N+1 query problem.
For issues with a large number of changelog entries, Jira fetches metadata for each changelog in a separate database query, sometimes with additional queries for permission checks, resulting in significant performance degradation.
Steps to Reproduce
1. Create an issue and perform a large number of updates to generate a substantial changelog history.
2. Trigger a webhook (e.g., issue updated).
3. Observe the time taken to generate and deliver the webhook payload.
Expected Results
Webhook payloads are generated efficiently, with changelog items fetched in a performant, batched manner.
Actual Results
Webhook payload generation is slow. Profiling shows that fetching changelog metadata dominates serialization time due to N+1 queries, for example:
// ... com.atlassian.jira.entity.property.BaseEntityPropertyService.getProperty(BaseEntityPropertyService.java:197) com.atlassian.jira.entity.property.BaseEntityPropertyService.getProperty(BaseEntityPropertyService.java:158) com.atlassian.jira.issue.changehistory.metadata.DefaultHistoryMetadataManager.getHistoryMetadata(DefaultHistoryMetadataManager.java:50) jdk.internal.reflect.GeneratedMethodAccessor1828.invoke(Unknown Source) jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@17.0.16/DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(java.base@17.0.16/Method.java:569) com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26) jdk.proxy3.$Proxy720.getHistoryMetadata(jdk.proxy3/Unknown Source) jdk.internal.reflect.GeneratedMethodAccessor1828.invoke(Unknown Source) jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(java.base@17.0.16/DelegatingMethodAccessorImpl.java:43) java.lang.reflect.Method.invoke(java.base@17.0.16/Method.java:569) org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.doInvoke(ServiceInvoker.java:56) org.eclipse.gemini.blueprint.service.importer.support.internal.aop.ServiceInvoker.invoke(ServiceInvoker.java:60) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invokeUnprivileged(ServiceTCCLInterceptor.java:70) org.eclipse.gemini.blueprint.service.util.internal.aop.ServiceTCCLInterceptor.invoke(ServiceTCCLInterceptor.java:53) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) org.eclipse.gemini.blueprint.service.importer.support.LocalBundleContextAdvice.invoke(LocalBundleContextAdvice.java:57) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) org.springframework.aop.support.DelegatingIntroductionInterceptor.doProceed(DelegatingIntroductionInterceptor.java:137) org.springframework.aop.support.DelegatingIntroductionInterceptor.invoke(DelegatingIntroductionInterceptor.java:124) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:241) jdk.proxy170.$Proxy3257.getHistoryMetadata(jdk.proxy170/Unknown Source) com.atlassian.jira.rest.v2.issue.builder.ChangelogBeanBuilder.makeChangeHistoryBean(ChangelogBeanBuilder.java:57) com.atlassian.jira.rest.v2.issue.builder.ChangelogBeanBuilder.build(ChangelogBeanBuilder.java:69) com.atlassian.jira.plugins.webhooks.serializer.issue.IssueEventSerializer.getChangelog(IssueEventSerializer.java:79) com.atlassian.jira.plugins.webhooks.serializer.issue.IssueEventSerializer.putFields(IssueEventSerializer.java:60) com.atlassian.jira.plugins.webhooks.serializer.issue.IssueEventSerializer.putFields(IssueEventSerializer.java:27) com.atlassian.jira.plugins.webhooks.serializer.AbstractJiraEventSerializer.build(AbstractJiraEventSerializer.java:24)
Workaround
Currently there is no known workaround for this behavior. A workaround will be added here when available.
- causes
-
JRASERVER-67865 Activity Stream is timing out when both comments and history entry number for an issue is too high
-
- Gathering Impact
-
- relates to
-
JRASERVER-79070 Webhook payloads generated for all webhooks cause performance issues
-
- Closed
-
-
JRASERVER-78911 Slow issue JSON generation (webhooks/REST API) in Jira Data Center when custom fields are overly scoped
-
- In Review
-