Rate Limiting in Modelica

Here’s the translation of the Go rate limiting example to Modelica, formatted in Markdown suitable for Hugo:

Rate limiting is an important mechanism for controlling resource utilization and maintaining quality of service. Modelica can support rate limiting using timers and events.

model RateLimiting
  import Modelica.Utilities.Streams.*;
  import Modelica.SIunits.Time;

  constant Integer numRequests = 5;
  discrete Integer[numRequests] requests;
  discrete Real[numRequests] requestTimes;
  
  discrete Integer burstyRequests[numRequests];
  discrete Real burstyRequestTimes[numRequests];
  
  parameter Time limitInterval = 0.2;
  discrete Time nextAllowedTime;
  
  discrete Integer burstyLimiterCount(start=3);
  parameter Integer burstyLimiterMax = 3;
  
initial equation
  for i in 1:numRequests loop
    requests[i] = i;
    burstyRequests[i] = i;
  end for;
  nextAllowedTime = time;

algorithm
  when time >= pre(nextAllowedTime) and time >= 0 and time < 1 then
    for i in 1:numRequests loop
      requestTimes[i] := time;
      nextAllowedTime := time + limitInterval;
      printString("request " + String(requests[i]) + " at time " + String(time) + "\n");
    end for;
  end when;
  
  when time >= 1 and time < 2 then
    if pre(burstyLimiterCount) > 0 then
      burstyLimiterCount := pre(burstyLimiterCount) - 1;
      for i in 1:min(pre(burstyLimiterCount), numRequests) loop
        burstyRequestTimes[i] := time;
        printString("bursty request " + String(burstyRequests[i]) + " at time " + String(time) + "\n");
      end for;
    end if;
  end when;
  
  when sample(1, limitInterval) then
    if pre(burstyLimiterCount) < burstyLimiterMax then
      burstyLimiterCount := pre(burstyLimiterCount) + 1;
    end if;
    if pre(burstyLimiterCount) <= numRequests then
      burstyRequestTimes[pre(burstyLimiterCount)] := time;
      printString("bursty request " + String(burstyRequests[pre(burstyLimiterCount)]) + " at time " + String(time) + "\n");
    end if;
  end when;

end RateLimiting;

In this Modelica implementation:

  1. We define arrays to represent the requests and their timestamps.

  2. The nextAllowedTime variable acts as our rate limiter, ensuring requests are processed at the specified interval.

  3. For basic rate limiting, we use a when clause that triggers every limitInterval (200 ms in this case), processing one request at a time.

  4. For bursty rate limiting, we implement a token bucket-like system using burstyLimiterCount. It starts with 3 tokens and refills every 200 ms.

  5. The bursty requests are processed immediately if tokens are available, otherwise they wait for the next token to become available.

Running this model would produce output similar to the following:

request 1 at time 0
request 2 at time 0.2
request 3 at time 0.4
request 4 at time 0.6
request 5 at time 0.8
bursty request 1 at time 1
bursty request 2 at time 1
bursty request 3 at time 1
bursty request 4 at time 1.2
bursty request 5 at time 1.4

This output demonstrates both the regular rate limiting (every 200 ms) and the bursty rate limiting (allowing up to 3 requests immediately, then reverting to the regular rate).

Note that Modelica, being primarily used for physical system modeling, doesn’t have built-in constructs for some concepts like channels or goroutines. This implementation uses Modelica’s event-based system to simulate similar behavior.