class_docstr: Simple rate limiter
  
  Inheriting from this class and decorate any class methods will
  apply simple rate limit.
  It will limit the maximal number of concurrent invocations of **all** the
  methods decorated.
  
  The below Example class will only allow 10 concurrent calls to A() and B()
  
  E.g.:
  
      class Example(RateLimitedModule):
          def __init__(self):
              super().__init__(max_num_call=10)
  
          @RateLimitedModule.enforce_max_concurrent_calls
          async def A():
              ...
  
          @RateLimitedModule.enforce_max_concurrent_calls
          async def B():
              ...
  
          async def limit_handler_(self):
              raise RuntimeError("rate limited reached!")
class_docstr_tok: ["Simple","rate","limiter","Inheriting","from","this","class","and","decorate","any","class","methods","will","apply","simple","rate","limit",".","It","will","limit","the","maximal","number","of","concurrent","invocations","of","*","*","all","*","*","the","methods","decorated",".","The","below","Example","class","will","only","allow","10","concurrent","calls","to","A","(",")","and","B","(",")","E.g",".",":","class","Example","(","RateLimitedModule",")",":","def","__init__","(","self",")",":","super","(",")",".__init__","(","max_num_call=10",")","@","RateLimitedModule.enforce_max_concurrent_calls","async","def","A","(",")",":","...","@","RateLimitedModule.enforce_max_concurrent_calls","async","def","B","(",")",":","...","async","def","limit_handler_","(","self",")",":","raise","RuntimeError","(","``","rate","limited","reached","!","''",")"]
docstr: Decorator to enforce max number of invocations of the decorated func
  
  NOTE: This should be used as the innermost decorator if there are multiple
  ones.
  
  E.g., when decorating functions already with @routes.get(...), this must be
  added below then the routes decorators:
      ```
      @routes.get('/')
      @RateLimitedModule.enforce_max_concurrent_calls
      async def fn(self):
          ...
  
      ```
docstr_tok: ["Decorator","to","enforce","max","number","of","invocations","of","the","decorated","func","NOTE",":","This","should","be","used","as","the","innermost","decorator","if","there","are","multiple","ones",".","E.g.",",","when","decorating","functions","already","with","@","routes.get","(","...",")",",","this","must","be","added","below","then","the","routes","decorators",":","``","`","@","routes.get","(","'\/","'",")","@","RateLimitedModule.enforce_max_concurrent_calls","async","def","fn","(","self",")",":","...","``","`"]
code: def enforce_max_concurrent_calls(func):
      """Decorator to enforce max number of invocations of the decorated func
  
      NOTE: This should be used as the innermost decorator if there are multiple
      ones.
  
      E.g., when decorating functions already with @routes.get(...), this must be
      added below then the routes decorators:
          ```
          @routes.get('/')
          @RateLimitedModule.enforce_max_concurrent_calls
          async def fn(self):
              ...
  
          ```
      """
  
      async def async_wrapper(self, *args, **kwargs):
          if (
              self.max_num_call_ >= 0
              and self.num_call_ >= self.max_num_call_
          ):
              if self.logger_:
                  self.logger_.warning(
                      f"Max concurrent requests reached={self.max_num_call_}"
                  )
              return await self.limit_handler_()
          self.num_call_ += 1
          try:
              ret = await func(self, *args, **kwargs)
          finally:
              self.num_call_ -= 1
          return ret
  
      # Returning closure here to avoid passing 'self' to the
      # 'enforce_max_concurrent_calls' decorator.
      return async_wrapper
  
imports: import asyncio
  import logging
  from dataclasses import asdict
  from datetime import datetime
  from typing import Callable, List, Tuple, Optional
  import aiohttp.web
  from aiohttp.web import Response
  from abc import ABC, abstractmethod
  from ray._private.usage.usage_lib import TagKey, record_extra_usage_tag
  import ray.dashboard.optional_utils
  import ray.dashboard.utils
  from ray.dashboard.consts import RAY_STATE_SERVER_MAX_HTTP_REQUEST, RAY_STATE_SERVER_MAX_HTTP_REQUEST_ALLOWED, RAY_STATE_SERVER_MAX_HTTP_REQUEST_ENV_NAME
  from ray.dashboard.datacenter import DataSource
  from ray.dashboard.modules.log.log_manager import LogsManager
  from ray.dashboard.optional_utils import rest_response
  from ray.dashboard.state_aggregator import StateAPIManager
  from ray.dashboard.utils import Change
  from ray.util.state.common import RAY_MAX_LIMIT_FROM_API_SERVER, ListApiOptions, GetLogOptions, PredicateType, SupportedFilterType, SummaryApiOptions, SummaryApiResponse, DEFAULT_RPC_TIMEOUT, DEFAULT_LIMIT, DEFAULT_LOG_LIMIT
  from ray.util.state.exception import DataSourceUnavailable
  from ray.util.state.state_manager import StateDataSourceClient
  from ray.util.state.util import convert_string_to_type
label_desc: Use image node_id 2 for calling the RateLimitedModule obj's underlying member method code with example usage: obj.enforce_max_concurrent_calls(func) and returns: async_wrapper, ret, unknown