Hi there,
Recently we were reported of slowness in Bob swift Attachment Table macro.
For information attachment-table macro does following steps,
- For each given space, gets the page list
- For each page, check view permission for logged in user and if permitted, list attachments of pages.
- For each attachment, fetch the properties like name, size, comment, creator, created date, etc
While troubleshooting macro code, we found that Confluence takes time at step 2.
To minimise the time, we created fixedThreadPool of size 1 ( if pool size > 1, then Confluence threw same below exception, so we tried with pool size = 1) and assigned every page to a thread i.e the thread will perform the task of getting list of attachments.
With this, we are able to save time in step 2 but Confluence throws below exception in step 3 every time while getting filesize property of the attachment i.e attachment.getFileSize();
2019-08-13 06:26:14,259 WARN [http-nio-8090-exec-105][engine.loading.internal.LoadContexts] cleanup HHH000100: Fail-safe cleanup (collections) : org.hibernate.engine.loading.internal.CollectionLoadContext@668ac984<rs=com.mchange.v2.c3p0.impl.NewProxyResultSet@504add1a [wrapping: null]>
– url: /display/AMTEST/Test-all+spaces | page: 350192291 | traceId: 19e938c7951b6943 | userName: advtables | referer: https://confluence6151.bobfire.com/display/AMTEST/Test-all+spaces | action: viewpage
2019-08-13 06:26:14,261 ERROR [http-nio-8090-exec-105][swift.confluence.table.AttachmentTableMacro] execute
– url: /display/AMTEST/Test-all+spaces | page: 350192291 | traceId: 19e938c7951b6943 | userName: advtables | referer: https://confluence6151.bobfire.com/display/AMTEST/Test-all+spaces | action: viewpage
org.hibernate.HibernateException: Unable to resolve owner of loading collection [[com.atlassian.confluence.core.ContentEntityObject.contentProperties#347146581](https://ecosystem.atlassian.net/servicedesk/customer/portal/14/DEVHELP-3294#347146581)] for second level caching
at org.hibernate.engine.loading.internal.CollectionLoadContext.addCollectionToCache(CollectionLoadContext.java:321)
Please find the complete stacktrace is in the attachment.
Here is the code where we are creating thread pool of size 1,
final ExecutorService pool = Executors.newFixedThreadPool(1);
Collection<Future<?>> futures = new LinkedList<>();
for (Page page : pageList) {
futures.add(pool.submit(new Callable<String>() {
@Override
public String call() throws Exception
{ pageCounter.addAndGet(1); attachmentTableHelper.processForPage(info, list, page, pagePattern, pageLabelPattern, limit); //checks view permission on the page and add the attachments of page to the given synchronized list return page.getTitle(); }
}));
}
for (Future<?> f : futures) {
try
{ f.get(); }
catch (InterruptedException e) {
log.error("futureget - InterruptedException {} ", e.getMessage());
} catch (ExecutionException e) {
log.error("futureget - ExecutionException {} ", e.getMessage());
}
}
shutdownAndAwaitTermination(pool);
After attachment list is ready, we are looping through to get properties of each attachment in a old fashioned for loop. And at this moment it fails with above exception. Logically we have the attachment list ready and thread pool is shutdown and as we are looping thru the attachment list sequentially, it shall go smooth.
This problem is observed only when we have separate thread.
Is there an alternate get the attachments in thread-safe way ? Or is there an alternate to get the attachments without spanning separate thread?
Appreciate your help here.
Thank you (23.8 KB)