Rate Limiting in Objective-C

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

Rate limiting is an important mechanism for controlling resource utilization and maintaining quality of service. Objective-C can implement rate limiting using Grand Central Dispatch (GCD) and timers.

#import <Foundation/Foundation.h>

@interface RateLimiter : NSObject

- (void)processRequests;
- (void)processBurstyRequests;

@end

@implementation RateLimiter

- (void)processRequests {
    dispatch_queue_t queue = dispatch_queue_create("com.example.ratelimiter", DISPATCH_QUEUE_SERIAL);
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 200 * NSEC_PER_MSEC, 100 * NSEC_PER_MSEC);
    
    __block int requestCount = 1;
    dispatch_source_set_event_handler(timer, ^{
        if (requestCount <= 5) {
            NSLog(@"request %d %@", requestCount, [NSDate date]);
            requestCount++;
        } else {
            dispatch_source_cancel(timer);
        }
    });
    
    dispatch_resume(timer);
}

- (void)processBurstyRequests {
    dispatch_queue_t queue = dispatch_queue_create("com.example.burstylimiter", DISPATCH_QUEUE_SERIAL);
    dispatch_semaphore_t semaphore = dispatch_semaphore_create(3);
    
    for (int i = 1; i <= 5; i++) {
        dispatch_async(queue, ^{
            dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
            NSLog(@"request %d %@", i, [NSDate date]);
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 200 * NSEC_PER_MSEC), queue, ^{
                dispatch_semaphore_signal(semaphore);
            });
        });
    }
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        RateLimiter *limiter = [[RateLimiter alloc] init];
        [limiter processRequests];
        [NSThread sleepForTimeInterval:2];
        [limiter processBurstyRequests];
        [[NSRunLoop currentRunLoop] run];
    }
    return 0;
}

This Objective-C implementation demonstrates rate limiting using Grand Central Dispatch (GCD) and semaphores. Let’s break it down:

  1. We define a RateLimiter class with two methods: processRequests and processBurstyRequests.

  2. In processRequests, we use a dispatch source timer to simulate rate limiting. It processes one request every 200 milliseconds, similar to the original example.

  3. processBurstyRequests uses a semaphore to allow bursts of up to 3 requests at a time, while still maintaining an overall rate limit.

  4. In the main function, we create an instance of RateLimiter and call both methods to demonstrate the different rate limiting approaches.

Running this program will output something like:

request 1 2023-06-01 12:34:56 +0000
request 2 2023-06-01 12:34:56 +0000
request 3 2023-06-01 12:34:56 +0000
request 4 2023-06-01 12:34:57 +0000
request 5 2023-06-01 12:34:57 +0000
request 1 2023-06-01 12:34:58 +0000
request 2 2023-06-01 12:34:58 +0000
request 3 2023-06-01 12:34:58 +0000
request 4 2023-06-01 12:34:58 +0000
request 5 2023-06-01 12:34:59 +0000

The first batch of requests is processed once every ~200 milliseconds. For the second batch (bursty requests), the first 3 are processed immediately, and the remaining 2 are processed with a delay, demonstrating the bursty behavior while still maintaining an overall rate limit.

This implementation showcases how to achieve rate limiting in Objective-C using GCD, which is more idiomatic for iOS and macOS development compared to channels and goroutines in the original example.