[BUG] Flex Repeater appears to be unstable

Greetings, I hope everyone is doing well. I’m running into a performance / stability issue with the Flex Repeater component.

Our server is running the Perspective module version 1.0.9 (b2020021812).

NOTE: To preface this, the saved & committed view renders okay in the browser, with none of the troubles I see in the Designer appearing to be present.

NOTE: I’ve tested this in both the Linux and Windows variants of the Designer with identical results

The behavior in the designer, loosely speaking, goes something like this: Whenever the view is loaded or reloaded, components tend to throw errors about the maximum call stack being reached:

[Browser Events Thread] INFO Perspective.Designer.BrowserConsole - RangeError: Maximum call stack size exceeded
[Browser Events Thread] INFO Perspective.Designer.BrowserConsole - ui.ErrorBoundary: Component error caught in error boundary: undefined

I observe 3 possible states that the view can load with:

  1. The view will load with some of the embedded views in the FlexRepeater not loading correctly, and some of them displaying normally, never randomly dispersed. The embedded views at the top, (presumably the views loaded first) are in an error state and the bottom (presumable the more recently loaded views) are displaying normally.

To reiterate, this is behavior seen exclusively within the Designer.

  1. The alternate behavior to this is having the embedded views show in an error boundary state, but I can still deep select components

  2. The worst state is having the entire view in an error boundary state, or similar to the 2nd state described. Attempting to deep select any other component fails and no actions can be taken on that view currently being edited. Attempting to toggle the view between preview / design mode does nothing as well. On closing the view through the designer, I get this exception in the designer console (With the gateway log indicating nothing unusual):

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
        at com.inductiveautomation.perspective.designer.workspace.ViewWorkspace$Actions.updateDeepSelectionToolbar(ViewWorkspace.java:654)
        at com.inductiveautomation.ignition.client.util.EDTUtil$ProcessQueue.run(EDTUtil.java:127)
        at java.desktop/java.awt.event.InvocationEvent.dispatch(Unknown Source)
        at java.desktop/java.awt.EventQueue.dispatchEventImpl(Unknown Source)
        at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
        at java.desktop/java.awt.EventQueue$4.run(Unknown Source)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.base/java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
        at java.desktop/java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.desktop/java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.desktop/java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.desktop/java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.desktop/java.awt.EventDispatchThread.run(Unknown Source)

The targeted embedded view has:

38 property bindings, no transformations
1 binding with a script transformation

The params to the view are all inputs.

One input param has a change script that calls a custom method on the root component, which has a script that looks like this:

def updateDisplay(self):
	if self.view.params.display == False:
		self.view.props.defaultSize.height = 0
		self.meta.visible = False
	else:
		self.meta.visible = False
		if self.view.params.variable == 0:
			self.getChild("child1").position.display = True
			self.view.props.defaultSize.height = 78
			self.getChild("child2").getChild("child1").getChild("child1").meta.visible = False
		else:
			self.getChild("child1").position.display = False
			self.view.props.defaultSize.height = 39
			self.getChild("child2").getChild("child1").getChild("child1").meta.visible = True

With my testing I have 31 instances defined in the flex repeater (The instance objects are never dynamically created, the object structures are static), which means it has to evaluate 1178 bindings in 31 separate views, with each view running the above script on their own view on load. To me, this is probably a bit much for the server / client framework to handle at once but I don’t think I’ll be the last person attempting this sort of feat with Perspective.

I’m researching different avenues to workaround this shortcoming, but I thought it would help to share my findings so that perhaps the Flex Repeater can be more useful in the future.

You should update - I’m pretty sure there are two separate issues you described that we’ve already fixed.

I’ll give that a shot and see if the issue is resolved. I’m relieved to say the least that it is something you’ve seen before!

Using version 8.0.12 appears to have solved my problem. The designer no longer exhibits the described states.

I’m glad it was fixed before I found it, and all I needed to do is jump to a newer version!

Thank you!

1 Like

Good to hear! Always good when it’s a nice easy fix :slight_smile: