Rate Limiting in Pascal

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

program RateLimiting;

uses
  SysUtils, DateUtils;

type
  TRequest = record
    Id: Integer;
    Time: TDateTime;
  end;

var
  Requests: array of TRequest;
  BurstyRequests: array of TRequest;

procedure ProcessRequests(const ARequests: array of TRequest; const ADelay: Integer);
var
  I: Integer;
begin
  for I := Low(ARequests) to High(ARequests) do
  begin
    Sleep(ADelay);
    WriteLn(Format('request %d %s', [ARequests[I].Id, FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', ARequests[I].Time)]));
  end;
end;

procedure ProcessBurstyRequests(const ARequests: array of TRequest; const ADelay: Integer; const ABurstSize: Integer);
var
  I: Integer;
begin
  for I := Low(ARequests) to High(ARequests) do
  begin
    if I >= ABurstSize then
      Sleep(ADelay);
    WriteLn(Format('request %d %s', [ARequests[I].Id, FormatDateTime('yyyy-mm-dd hh:nn:ss.zzz', ARequests[I].Time)]));
  end;
end;

begin
  // First we'll look at basic rate limiting. Suppose
  // we want to limit our handling of incoming requests.
  SetLength(Requests, 5);
  for I := 0 to 4 do
  begin
    Requests[I].Id := I + 1;
    Requests[I].Time := Now;
  end;

  // This will process requests with a 200 millisecond delay between each
  ProcessRequests(Requests, 200);

  WriteLn;

  // Now simulate 5 more incoming requests. The first
  // 3 of these will benefit from the burst capability.
  SetLength(BurstyRequests, 5);
  for I := 0 to 4 do
  begin
    BurstyRequests[I].Id := I + 1;
    BurstyRequests[I].Time := Now;
  end;

  // This will process the first 3 requests immediately, then add a 200 millisecond delay for the rest
  ProcessBurstyRequests(BurstyRequests, 200, 3);
end.

In this Pascal version, we’ve implemented a simple rate limiting mechanism. Here’s an explanation of the key parts:

  1. We define a TRequest record to hold the request ID and timestamp.

  2. We create two procedures: ProcessRequests and ProcessBurstyRequests. These simulate the rate limiting behavior.

  3. ProcessRequests adds a delay between each request, simulating basic rate limiting.

  4. ProcessBurstyRequests allows a burst of requests (specified by ABurstSize) to be processed immediately, then adds delays for subsequent requests.

  5. In the main program, we create two sets of requests: one for basic rate limiting and one for bursty rate limiting.

  6. We process the first set of requests with a consistent delay between each request.

  7. We then process the second set of requests, allowing a burst of 3 requests before applying delays.

This implementation doesn’t use channels or goroutines as Pascal doesn’t have these concepts. Instead, we use simple arrays and loops to simulate the behavior. The Sleep function is used to introduce delays, simulating the rate limiting effect.

When you run this program, you’ll see output similar to the following:

request 1 2023-06-01 10:00:00.000
request 2 2023-06-01 10:00:00.200
request 3 2023-06-01 10:00:00.400
request 4 2023-06-01 10:00:00.600
request 5 2023-06-01 10:00:00.800

request 1 2023-06-01 10:00:01.000
request 2 2023-06-01 10:00:01.000
request 3 2023-06-01 10:00:01.000
request 4 2023-06-01 10:00:01.200
request 5 2023-06-01 10:00:01.400

Note that the actual timestamps will depend on when you run the program. The important thing to observe is the timing between requests, especially in the bursty scenario where the first three requests are processed immediately.