Request Time Out system.util.sendRequest When Adding or Editing or Deleting User from Hybrid User Source

I essentially created a custom User Management component out of templates so users can edit the project’s user source. I decided to make a custom user management template for 2 reasons. 1) To more easily match the project’s theme colors / button icons. 2) Users are not concerned with roles or schedules.

The user source for the project is AD/Hybrid type and the user management template copies users over from the root AD user source. This is so that contact information and names can be changed outside of the AD source.

I am having issues with system.user.addUser and system.user.editUser freezing up.

I tried running them in the client, but this would freeze the GUI with errors. I then ran it on an asynch thread, but had the same issue. Now, I am using system.util.sendRequest() to add and edit users. This SOMETIMES works very fast and other times will not return, throw errors, but the user source will have been edited correctly.

Here is the call to the sendRequest when the user presses a save button:

	# Get data
	templateRef = event.source.parent.parent.getComponent('Container Body').getComponent('Edit User').getComponent('User Template').getComponent(0)
	username = templateRef.getComponent("ID").text
	firstname = templateRef.getComponent("User Properties").getComponent("First Name").text
	lastname = templateRef.getComponent("User Properties").getComponent("Last Name").text
	notes = templateRef.getComponent("User Properties").getComponent("Text Notes").text
	contactDataset = templateRef.getComponent("User Properties").getComponent("Contact Info").data
	
	# Adding User
	if event.source.parent.parent.getComponent('Container Body').getComponent('Edit User').getComponent('User Template').Add:
		payload = {"add": True, "username": username, "firstName": firstname, "lastName": lastname, "notes": notes, "contactDataset": contactDataset}

	# Editing User
	else:
		payload = {"edit": True, "username": username, "firstName": firstname, "lastName": lastname, "notes": notes, "contactDataset": contactDataset}
		
	def editUser(event = event, payload = payload):
		try:		
			# Call gateway message function
			response = system.util.sendRequest("Custom_Tag_Alarming", "editUser", payload = payload, timeoutSec = 60)
			def updateScreen(event = event, response = response):
				# Reset variables
				event.source.parent.parent.getComponent('Container Body').getComponent('Users').getComponent('User Template').UserToView = ""
				event.source.parent.parent.getComponent('Container Body').getComponent('Users').getComponent('User Template').UserToEdit = ""
				event.source.parent.parent.getComponent('Container Body').getComponent('Users').getComponent('User Template').UserToAdd = False
				
				# Disable
				event.source.parent.parent.getComponent('Container Body').getComponent('Edit User').getComponent('User Template').Enabled = False
				event.source.parent.parent.getComponent('Container Body').getComponent('Edit User').getComponent('User Template').Add = False
				event.source.parent.parent.getComponent('Container Body').getComponent('Edit User').getComponent('User Template').EditContact = False
				event.source.parent.parent.getComponent('Container Body').getComponent('Edit User').getComponent('User Template').RACFID = ""
				event.source.parent.parent.getComponent('Container Body').getComponent('Edit User').visible = False
				
				# Update user dataset and turn off the loading and give success message
				event.source.parent.parent.getComponent('Container Body').getComponent('Users').getComponent('User Template').Users = CustomAlarm.getUserSourceDataset()
				event.source.parent.parent.Loading = False
				if response["success"]:
					system.gui.messageBox("User " + firstname + " was saved successfully.")
				else:
					system.gui.messageBox(response["error"])
			# Invoke function on GUI
			system.util.invokeLater(updateScreen)
		# If the request times out, then close and re-open the window
		except:
			def refreshWindow():
				openedWindows = system.gui.getOpenedWindows()
				for window in openedWindows:
					system.nav.closeWindow(window)
				system.nav.openWindow("90 - Roster Management")
			system.util.invokeLater(refreshWindow)
	system.util.invokeAsynchronous(editUser)
	event.source.parent.parent.Loading = True

Here is the function in the “editUser” message on the gateway:

# Initialize return variables
	success = False
	error = None

	db = ""
	dbTag = system.tag.readBlocking(["[default]Custom_Tag_Alarming/Database Name"])
	if dbTag:
		db = dbTag[0].value
	else:
		error = "Error. Cannot read tag 'Database Name'."
		return {"success": success, "error": error}
	
	# Get Custom Alarms user source and d user source
	tagResults = system.tag.readBlocking(["[default]Custom_Tag_Alarming/User Source", "[default]Custom_Tag_Alarming/D User Source"])
	userSource = tagResults[0].value
	dUserSource = tagResults[1].value
	
	# Used to edit user attributes with a give user object
	def setUserAttributes(userObj = None, payload = payload):
		# If user exists
		if userObj:
			userObj.set("firstname", payload["firstName"])							# First name
			userObj.set("lastname", payload["lastName"])							# Last name
			userObj.set("notes", payload["notes"])									# Notes
			originalContactInfo = userObj.getContactInfo()							# Contact Info
			contactDataset = payload["contactDataset"]
			for originalContact in originalContactInfo:							# Delete all original contact info
				userObj.removeContactInfo(originalContact.getContactType(), originalContact.getValue())
			for rowIndex in range(contactDataset.getRowCount()):					# Add all configured contact info
				type = contactDataset.getValueAt(rowIndex, "Type")
				type = type.lower()													# In user source on gateway as all lower case
				userObj.addContactInfo({type: contactDataset.getValueAt(rowIndex, "Value")})
		return userObj
	
	# Add User
	if "add" in payload:
		if payload["add"]:
			userObj = system.user.getUser(dUserSource, payload["username"])
			newUser = setUserAttributes(userObj, payload)
			if newUser:
				userSourceResponse = system.user.addUser(userSource, newUser)
				responseErrors = userSourceResponse.getErrors()
				if len(responseErrors) > 0:
					error = "Error. Unable to add user. See the following errors:\n"
					for responseError in responseErrors:
						error += responseError + "\n"
				else:
					success = True
			else:
				error = "Error. User not found."
		
	# Edit User
	elif "edit" in payload:
		if payload["edit"]:
			userObj = system.user.getUser(userSource, payload["username"])
			newUser = setUserAttributes(userObj, payload)
			if newUser:
				userSourceResponse = system.user.editUser(userSource, newUser)
				responseErrors = userSourceResponse.getErrors()
				if len(responseErrors) > 0:
					error = "Error. Unable to edit user. See the following errors:\n"
					for responseError in responseErrors:
						error += responseError + "\n"
				else:
					success = True
			else:
				error = "Error. User not found."

	elif "delete" in payload:
		if payload["delete"]:
			userSourceResponse = system.user.removeUser(userSource, payload["username"])
			responseErrors = userSourceResponse.getErrors()
			if len(responseErrors) > 0:
				error = "Error. Unable to delete user. See the following errors:\n"
				for responseError in responseErrors:
					error += responseError + "\n"
			else:
				success = True
	
	# Return boolean for success and a string description of the error if there is any
	return {"success": success, "error": error}

I remake the entire user when editing, so I’m not sure if that is an issue. However, I also receive timeout when adding and deleting users, but again the changes are successfully reflected in the user source.

Any help would be much appreciate!