Skip to content
DataMiner Dojo

More results...

Generic selectors
Exact matches only
Search in title
Search in content
Post Type Selectors
Search in posts
Search in pages
Search in posts
Search in pages
Log in
Menu
  • Updates & Insights
  • Questions
  • Learning
    • E-learning Courses
    • Tutorials
    • Open Classroom Training
    • Certification
      • DataMiner Fundamentals
      • DataMiner Configurator
      • DataMiner Automation
      • Scripts & Connectors Developer: HTTP Basics
      • Scripts & Connectors Developer: SNMP Basics
      • Visual Overview – Level 1
      • Verify a certificate
    • YouTube Videos
    • Solutions & Use Cases
      • Solutions
      • Use Case Library
    • Agility
      • Learn more about Agile
        • Agile Webspace
        • Everything Agile
          • The Agile Manifesto
          • Best Practices
          • Retro Recipes
        • Methodologies
          • The Scrum Framework
          • Kanban
          • Extreme Programming
        • Roles
          • The Product Owner
          • The Agile Coach
          • The Quality & UX Coach (QX)
      • Book your Agile Fundamentals training
      • Book you Kanban workshop
    • >> Go to DataMiner Docs
  • DevOps
    • About the DevOps Program
    • Sign up for the DevOps Program
    • DataMiner DevOps Support
    • Feature Suggestions
  • Downloads
  • Swag Shop
  • PARTNERS
    • Business Partners
    • Technology Partners
  • Contact
    • Sales, Training & Certification
    • DataMiner Support
    • Global Feedback Survey
  • >> Go to dataminer.services

Improving Performance of Periodic API Monitoring (Batch Handling Without Multithreaded Timer)

134 views18 hours ago#BatchUpdate #PeriodicRequestToMultipleURLs performance
3
Srimathi Ramachandran [DevOps Member]162 3 days ago 0 Comments

Hi all,

I have a QAction that runs every hour to monitor the software status of multiple devices. I maintain a table that stores the device URLs along with credentials and their API status. This QAction calls {DeviceURL}/api/system for each device and updates the status back in the table.

The issue is that the number of devices is dynamic and can vary, and currently processing the full table takes around 15 minutes because each endpoint is being hit and updated one by one. The list can be quite large, and the device count is not predictable. I’m trying to improve the performance and handle the calls more efficiently in batches. I cannot rely on a multithreaded timer since the number of endpoints is unknown.

At the moment, I’m creating tasks for each device and attempting to process them in batches. I’m looking for a better way to manage a large and dynamic number of HTTP calls with proper batching (update the rows in batch without much wait time to process the whole list) or throttling.

Any suggestions on how to restructure this for better performance would be really helpful.

public static void Run(SLProtocolExt protocol)
{
try
{
var devicesTable = Element.GetRows<DevicesQActionRow>(protocol, protocol.devices.TableId);
var tasks = new List<Task>();

var totalDevices = devicesTable.Count();

for (int i = 0; i < totalDevices; i += _batchSize)
{
var batch = devicesTable.Skip(i).Take(_batchSize).ToList();
tasks.AddRange(batch.Select(device => GetDeviceStatusAsync(device, protocol)).ToList());
Task.WhenAll(tasks);
}

protocol.Log($"Processed {tasks.Count} devices");

}
catch (Exception ex)
{
protocol.Log($"QA{protocol.QActionID}|{protocol.GetTriggerParameter()}|Run|Exception thrown:{Environment.NewLine}{ex}", LogType.Error, LogLevel.NoLogging);
}
}

private static async Task GetDeviceStatusAsync(DevicesQActionRow device, SLProtocolExt protocol)
{
var url = device.Deviceurl?.ToString();
var username = device.Deviceusername?.ToString();
var password = device.Devicepassword?.ToString();
var row = (DevicesQActionRow)protocol.devices.GetRow(device.Deviceid.ToString());
if (string.IsNullOrWhiteSpace(url))
{
return;
}
var path = new Uri(url + "/api/system");
try
{
var response = ExtensionMethods.GetResponseAsync(path, true, protocol, username, password).Result;

if (!string.IsNullOrWhiteSpace(response) && response != "[]")
{
JObject jsonObject = JObject.Parse(response);
var statusCode = jsonObject["statusCode"].ToString();
if (string.Equals(jsonObject["success"].ToString().ToLower(), "true", StringComparison.InvariantCultureIgnoreCase))
{
row.Deviceurl = device.Deviceurl;
row.Deviceapistatus = statusCode + " OK";
}
else
{
row.Deviceurl = device.Deviceurl;
row.Deviceapistatus = statusCode;
}
protocol.devices.SetRow(row);
}
}
catch (Exception ex)
{

row.Deviceurl = device.Deviceurl;
row.Deviceapistatus = "Error";
protocol.devices.SetRow(row);
}
}

Tom Waterbley [SLC] [DevOps Enabler] Answered question 18 hours ago

1 Answer

  • Active
  • Voted
  • Newest
  • Oldest
0
Tom Waterbley [SLC] [DevOps Enabler]9.88K Posted 18 hours ago 0 Comments

Hi Srimathi,

I understand your concern about using a multithreaded timer when the number of endpoints is unknown. However, this is actually a good scenario to use one. A multithreaded timer ensures that each row in the table is processed at the defined interval, regardless of how many rows the table contains. Multithreaded timers are designed to handle such dynamic scenarios efficiently.

See the following page in the docs for more information:

https://docs.dataminer.services/develop/devguide/Connector/AdvancedMultithreadedTimers.html

https://docs.dataminer.services/develop/devguide/Connector/AdvancedMultithreadedTimersHttp.html.

Looking at the code snippet you shared, there are a couple of improvements that can be made:

1) Instead of calling the Result property after GetResponseAsync(), which makes it a synchrounous blocking call, it should be awaited:
var response = await ExtensionMethods.GetResponseAsync(path, true, protocol, username, password);

2) Task.WhenAll() returns a new task that completes when all provided tasks are finished, but in the current implementation, that task is not awaited. You can either use Task.WaitAll(tasks); or explicitly wait for completion like this:

Task.WhenAll(tasks).GetAwaiter().GetResult();

Tom Waterbley [SLC] [DevOps Enabler] Edited answer 18 hours ago
Please login to be able to comment or post an answer.

My DevOps rank

DevOps Members get more insights on their profile page.

My user earnings

0 Dojo credits

Spend your credits in our swag shop.

0 Reputation points

Boost your reputation, climb the leaderboard.

Promo banner DataMiner DevOps Professiona Program
DataMiner Integration Studio (DIS)
Empower Katas
Privacy Policy • Terms & Conditions • Contact

© 2026 Skyline Communications. All rights reserved.

DOJO Q&A widget

Can't find what you need?

? Explore the Q&A DataMiner Docs

[ Placeholder content for popup link ] WordPress Download Manager - Best Download Management Plugin