HTTPRequest : Wrong request.id in msg.name when doing multiple requests

I noticed that when making multiple requests in parallel, and some of them would terminate, eventually, the msg.name received would be reset to "1" instead of the expected request id. This causes confusion because the script thinks the request never returned (since the request with id 1 is already processed).
Unfortunately, I don't have an easy-to-use test script ready this time, but I can share one privately along with some directions to trigger the issue. Just let me know.
Thanks.

If you can provide a script to reproduce the issue that would be helpful.

I've made a 'quick n dirty' script for testing, hoping to clarify my point. The script loads 6 images from the GPSoft webpage gallery.
It use a Map of the sent requests, storing the request object using its req.id value. This allows retrieving the request object later based on its id.

function OnClick(clickData) {
	DOpus.ClearOutput();
	var total_items = 6;
	var req_map = DOpus.Create().OrderedMap();
	var processed_items = DOpus.Create().StringSet();
	var max_threads = 3;
	var dlg = {};
	dlg.main = clickData.func.Dlg();
	dlg.main.template = 'main';
	dlg.main.singleton = true;
	if (dlg.main.Create()) {
		dlg.img_1 = dlg.main.Control('img_1');
		dlg.img_2 = dlg.main.Control('img_2');
		dlg.img_3 = dlg.main.Control('img_3');
		dlg.img_4 = dlg.main.Control('img_4');
		dlg.img_5 = dlg.main.Control('img_5');
		dlg.img_6 = dlg.main.Control('img_6');

		var msg;
		dlg.main.Show();
		for (var curr_pos = 1; curr_pos <= max_threads; curr_pos++) {
			SendRequest('https://www.gpsoft.com.au/assets/img/gallery/gallery-' + curr_pos + '.png');
		}
		main_loop: while (true) {
			msg = dlg.main.GetMsg();
			if (!msg.result) break;
			if (msg.event == 'http') { 
				Log(1, '=> event : ' + msg.event + '\t; control : ' + msg.name + '\t; value : ' + msg.value);
				if (!req_map.Exists(msg.name)) {
					Log(3, '=>' + msg.name + ' request is not registered!');
					continue;
				}
				req = req_map(msg.name)('req');
				if (req.complete) {
					Log(1, 'Request ' + msg.name + ' is completed!');
					continue;
				}
				curr_item = req_map(msg.name)('item');
				if (processed_items.Exists(curr_item)) {
					Log(1, '=>' + curr_item + ' is already processed!');
					continue;
				}

				switch (msg.value) {
					case 'data':
						var reqData = req.ReadResponse();
						var ctrl = req_map(msg.name)('ctrl');
						if (DOpus.TypeOf(reqData) == 'object.Image' && ctrl in dlg)
							dlg[ctrl].title = reqData;
						StopProcessing(curr_item, 'complete');
						req.shutdown(); // if you comment this line, the issue does not happen
						break;
					case 'error':
						try {
							Log(3, curr_item + ' => ' + req.id + '=> ' + req.errorcode + ' : ' + req.errortext);
						}
						catch (err) {
							Log(3, curr_item + ' => ' + req.id + '=> Error : ' + err.description);
						}
						StopProcessing(curr_item, 'error');
						break;
				}
			}
		}
	}

	return;

	function StopProcessing(item, status) {
		Log(1, 'Stop processing ' + item);
		processed_items.insert(item);
		Log(1, 'processed_items=' + processed_items.size + ' : total_items=' + total_items);
		if (curr_pos <= total_items) {
			Log(1, 'Passing to next image...');
			SendRequest('https://www.gpsoft.com.au/assets/img/gallery/gallery-' + curr_pos + '.png');
			curr_pos++;
		}
	}

	function SendRequest(item) {
		try {
			if (item) {
				var req = dlg.main.NewHTTPReq();
				Log(1, ' => Sending request "' + req.id + '" for "' + item + '"...');

				req.SendRequest(item);
				Log(1, ' => Request "' + req.id + '" sent for "' + item + '"');
				req_map.Set(req.id, DOpus.NewMap('req', req, 'item', item, 'ctrl', 'img_' + req.id)); //req.id always increment by 1
			}
		}
		catch (err) {
			Log(3, '=> Error when sending request : ' + err.description);
			StopProcessing(item, 'error');
		}
	}
}

httprequest_test.dcf (9.2 KB)

You'll notice that the last 1–2 images don't load because msg.name resets to 1, causing a mismatch with the actual req.id.
Note that if you comment the line with req.shutdown();, the issue does not happen.

As a side note, it would be useful to have a way to bind a Map or another object when sending a request, which could later be retrieved in the msg.object property when the event triggers. That way you can send additional data (like the req object) without using others structures.

Thanks! Fixed in the next beta.

1 Like