changeset 5804:c3eeeb968403

mod_pubsub_serverinfo: Detect existence of pub/sub node Instead of blindly trying to create the pub/sub node to publish items to, a service discovery query is performed to check if node creation is required. Added various bits of warn and debug logging, to give a user better feedback if and why something is failing.
author Guus der Kinderen <guus.der.kinderen@gmail.com>
date Thu, 04 Jan 2024 11:59:35 +0100
parents f55e65315ba0
children 55b99f593c3a
files mod_pubsub_serverinfo/mod_pubsub_serverinfo.lua
diffstat 1 files changed, 78 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/mod_pubsub_serverinfo/mod_pubsub_serverinfo.lua	Wed Jan 03 23:05:14 2024 +0100
+++ b/mod_pubsub_serverinfo/mod_pubsub_serverinfo.lua	Thu Jan 04 11:59:35 2024 +0100
@@ -11,8 +11,15 @@
 local opt_in_reports
 
 function module.load()
-	-- Will error out with a 'conflict' if the node already exists. TODO: create the node only when it's missing.
-	create_node():next()
+	discover_node():next(
+		function(exists)
+			if not exists then create_node() end
+		end
+	):catch(
+		function(error)
+			module:log("warn", "Error prevented discovery or creation of pub/sub node at %s: %s", service, error)
+		end
+	)
 
 	module:add_feature("urn:xmpp:serverinfo:0");
 
@@ -29,7 +36,35 @@
 	delete_node(); -- Should this block, to delay unload() until the node is deleted?
 end
 
--- Returns a promise
+-- Returns a promise of a boolean
+function discover_node()
+    local request = st.iq({ type = "get", to = service, from = actor, id = new_id() })
+    	:tag("query", { xmlns = "http://jabber.org/protocol/disco#items" })
+
+	module:log("debug", "Sending request to discover existence of pub/sub node '%s' at %s", node, service)
+	return module:send_iq(request):next(
+		function(response)
+			if response.stanza == nil or response.stanza.attr.type ~= "result" then
+				module:log("warn", "Unexpected response to service discovery items request at %s: %s", service, response.stanza)
+				return false
+			end
+
+			local query = response.stanza:get_child("query", "http://jabber.org/protocol/disco#items")
+			if query ~= nil then
+				for item in query:childtags("item") do
+					if item.attr.jid == service and item.attr.node == node then
+						module:log("debug", "pub/sub node '%s' at %s does exists.", node, service)
+						return true
+					end
+				end
+			end
+			module:log("debug", "pub/sub node '%s' at %s does not exist.", node, service)
+			return false;
+		end
+	);
+end
+
+-- Returns a promise of a boolean
 function create_node()
 	local request = st.iq({ type = "set", to = service, from = actor, id = new_id() })
 		:tag("pubsub", { xmlns = "http://jabber.org/protocol/pubsub" })
@@ -44,16 +79,39 @@
 						:up()
 					:tag("field", { var = "pubsub#persist_items" })
 						:text_tag("value", "0")
-	return module:send_iq(request);
+
+	module:log("debug", "Sending request to create pub/sub node '%s' at %s", node, service)
+	return module:send_iq(request):next(
+		function(response)
+			if response.stanza == nil or response.stanza.attr.type ~= "result" then
+				module:log("warn", "Unexpected response to pub/sub node '%s' creation request at %s: %s", node, service, response.stanza)
+				return false
+			else
+				module:log("debug", "Successfully created pub/sub node '%s' at %s", node, service)
+				return true
+			end
+		end
+	)
 end
 
--- Returns a promise
+-- Returns a promise of a boolean
 function delete_node()
 	local request = st.iq({ type = "set", to = service, from = actor, id = new_id() })
 		:tag("pubsub", { xmlns = "http://jabber.org/protocol/pubsub" })
 			:tag("delete", { node = node });
 
-	return module:send_iq(request);
+	module:log("debug", "Sending request to delete pub/sub node '%s' at %s", node, service)
+	return module:send_iq(request):next(
+		function(response)
+			if response.stanza == nil or response.stanza.attr.type ~= "result" then
+				module:log("warn", "Unexpected response to pub/sub node '%s' deletion request at %s: %s", node, service, response.stanza)
+				return false
+			else
+				module:log("debug", "Successfully deleted pub/sub node '%s' at %s", node, service)
+				return true
+			end
+		end
+	)
 end
 
 function publish_serverinfo()
@@ -112,7 +170,20 @@
 
 	request:up():up()
 
-	module:send_iq(request):next()
+	module:send_iq(request):next(
+		function(response)
+			if response.stanza == nil or response.stanza.attr.type ~= "result" then
+				module:log("warn", "Unexpected response to item publication at pub/sub node '%s' on %s: %s", node, service, response.stanza)
+				return false
+			else
+				module:log("debug", "Successfully published item on pub/sub node '%s' at %s", node, service)
+				return true
+			end
+		end,
+		function(error)
+			module:log("warn", "Error prevented publication of item on pub/sub node at %s: %s", service, error)
+		end
+	)
 
 	return publication_interval;
 end