Skip to content

Commit

Permalink
Customizable polling timeout ms
Browse files Browse the repository at this point in the history
  • Loading branch information
huytool157 committed Jan 25, 2024
1 parent 36be251 commit ab47ab6
Show file tree
Hide file tree
Showing 10 changed files with 40 additions and 15 deletions.
2 changes: 2 additions & 0 deletions javascript/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const rpc = new RetoolRPC({
resourceId: 'resource-id', // Replace this resource ID with your ID
environmentName: 'production', // Replace this environment name with your name (defaults to production)
pollingIntervalMs: 1000, // The polling interval for the RPC
pollingTimeoutMs: 5000, // The polling interval for the RPC
version: '0.0.1', // An optional version number for functions schemas
logLevel: 'info', // Change to 'debug' for verbose logging or use own logger implementation by passing a logger param
})
Expand All @@ -57,6 +58,7 @@ await rpc.listen()
For users of [Sequelize](https://sequelize.org/), we offer an ORM mixin that enables the addition of fundamental model functions with a single function call, `registerModel`. When you register a model with `rpc`, it automatically registers various remote functions for the model, including `create`, `update`, `createOrUpdate`, `findByPk`, `findBy`, and `findAll`. You can find additional details [here](https://github.com/tryretool/retoolrpc/blob/main/javascript/src/addons/sequelize.ts#L5-L14).

Following is an example of registering a `User` model:

```javascript
import { RetoolRPC, sequelizeMixin } from 'retoolrpc'
import { User } from './orm/models' // the path to your model may be different
Expand Down
1 change: 1 addition & 0 deletions javascript/example.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ const rpc = new RetoolRPC({
resourceId: 'resource-uuid', // create a Retool RPC resource and copy its ID here
environmentName: 'production',
pollingIntervalMs: 1000,
pollingTimeoutMs: 5000,
logLevel: 'info',
})

Expand Down
11 changes: 9 additions & 2 deletions javascript/src/rpc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,13 @@ import { createAgentServerError, FunctionNotFoundError } from './utils/errors'
import { parseFunctionArguments } from './utils/schema'
import { isClientError } from './utils/helpers'
import { loopWithBackoff } from './utils/polling'
import { Logger, LoggerService } from './utils/logger';
import { Logger, LoggerService } from './utils/logger'
import { RetoolAPI } from './utils/api'
import { RetoolRPCVersion } from './version'

const MINIMUM_POLLING_INTERVAL_MS = 100
const DEFAULT_POLLING_INTERVAL_MS = 1000
const DEFAULT_POLLING_TIMEOUT_MS = 5000
const DEFAULT_ENVIRONMENT_NAME = 'production'
const DEFAULT_VERSION = '0.0.1'

Expand All @@ -31,6 +32,7 @@ export class RetoolRPC {
private _resourceId: string
private _environmentName: string
private _pollingIntervalMs: number
private _pollingTimeoutMs: number
private _version: string
private _agentUuid: string
private _versionHash: string | undefined
Expand All @@ -49,10 +51,15 @@ export class RetoolRPC {
this._pollingIntervalMs = config.pollingIntervalMs
? Math.max(config.pollingIntervalMs, MINIMUM_POLLING_INTERVAL_MS)
: DEFAULT_POLLING_INTERVAL_MS
this._pollingTimeoutMs = config.pollingTimeoutMs || DEFAULT_POLLING_TIMEOUT_MS
this._version = config.version || DEFAULT_VERSION
this._agentUuid = config.agentUuid || uuidv4()

this._retoolApi = new RetoolAPI({ hostUrl: this._hostUrl, apiKey: this._apiKey })
this._retoolApi = new RetoolAPI({
hostUrl: this._hostUrl,
apiKey: this._apiKey,
pollingTimeoutMs: this._pollingTimeoutMs || DEFAULT_POLLING_TIMEOUT_MS,
})
this._logger = config.logger ?? new Logger({ logLevel: config.logLevel })

this._logger.debug('Retool RPC Configuration', {
Expand Down
4 changes: 3 additions & 1 deletion javascript/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { LoggerService } from './utils/logger';
import type { LoggerService } from './utils/logger'

/**
* Configuration options for the Retool RPC.
Expand All @@ -19,6 +19,8 @@ export type RetoolRPCConfig = {
version?: string
/** The optional polling interval in milliseconds. Defaults to 1000. Minimum is 100. */
pollingIntervalMs?: number
/** The optional polling timeout in milliseconds. Defaults to 5000. */
pollingTimeoutMs?: number
/** The optional UUID of the agent. Will be automatically generated by default */
agentUuid?: string
/** The optional log level. */
Expand Down
10 changes: 5 additions & 5 deletions javascript/src/utils/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,6 @@ const AbortController = globalThis.AbortController || AbortControllerFallback
import { AgentServerError } from '../types'
import { RetoolRPCVersion } from '../version'

const POLLING_TIMEOUT_MS = 5 * 1000 // 5 seconds

type PopQueryRequest = {
resourceId: string
environmentName: string
Expand Down Expand Up @@ -46,17 +44,19 @@ type PostQueryResponseRequest = {
export class RetoolAPI {
private _hostUrl: string
private _apiKey: string
private _pollingTimeoutMs: number

constructor({ hostUrl, apiKey }: { hostUrl: string; apiKey: string }) {
constructor({ hostUrl, apiKey, pollingTimeoutMs }: { hostUrl: string; apiKey: string; pollingTimeoutMs: number }) {
this._hostUrl = hostUrl
this._apiKey = apiKey
this._pollingTimeoutMs = pollingTimeoutMs
}

async popQuery(options: PopQueryRequest) {
const abortController = new AbortController()
setTimeout(() => {
abortController.abort()
}, POLLING_TIMEOUT_MS)
}, this._pollingTimeoutMs)

try {
return await fetch(`${this._hostUrl}/api/v1/retoolrpc/popQuery`, {
Expand All @@ -73,7 +73,7 @@ export class RetoolAPI {
})
} catch (error: any) {
if (abortController.signal.aborted) {
throw new Error(`Polling timeout after ${POLLING_TIMEOUT_MS}ms`)
throw new Error(`Polling timeout after ${this._pollingTimeoutMs}ms`)
}
throw error
}
Expand Down
10 changes: 9 additions & 1 deletion python/retoolrpc/rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

MINIMUM_POLLING_INTERVAL_MS = 100
DEFAULT_POLLING_INTERVAL_MS = 1000
DEFAULT_POLLING_TIMEOUT_MS = 5000
DEFAULT_ENVIRONMENT_NAME = "production"
DEFAULT_VERSION = "0.0.1"

Expand All @@ -38,10 +39,17 @@ def __init__(self, config: RetoolRPCConfig):
config.polling_interval_ms or DEFAULT_POLLING_INTERVAL_MS,
MINIMUM_POLLING_INTERVAL_MS,
)
self._polling_timeout_ms = (
config.polling_timeout_ms or DEFAULT_POLLING_TIMEOUT_MS
)
self._version = config.version or DEFAULT_VERSION
self._agent_uuid = config.agent_uuid or str(uuid.uuid4())

self._retool_api = RetoolAPI(host_url=self._host_url, api_key=self._api_key)
self._retool_api = RetoolAPI(
host_url=self._host_url,
api_key=self._api_key,
polling_timeout_ms=self._polling_timeout_ms,
)
self._logger = Logger(log_level=config.log_level)

self._logger.debug(
Expand Down
12 changes: 6 additions & 6 deletions python/retoolrpc/utils/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
from retoolrpc.utils.types import AgentServerError
from retoolrpc.version import __version__

# Defining constants and types
POLLING_TIMEOUT_MS = 5 * 1000 # 5 seconds


class PopQueryRequest(TypedDict):
"""
Expand Down Expand Up @@ -60,12 +57,13 @@ class PostQueryResponseRequest(TypedDict):


class RetoolAPI:
def __init__(self, host_url: str, api_key: str) -> None:
def __init__(self, host_url: str, api_key: str, polling_timeout_ms: int) -> None:
"""
Initialize the RetoolAPI with given host_url and api_key.
"""
self._host_url = host_url
self._api_key = api_key
self._polling_timeput_ms = polling_timeout_ms

async def pop_query(self, options: PopQueryRequest) -> httpx.Response:
headers = {
Expand All @@ -79,12 +77,14 @@ async def pop_query(self, options: PopQueryRequest) -> httpx.Response:
url=f"{self._host_url}/api/v1/retoolrpc/popQuery",
headers=headers,
json=options,
timeout=POLLING_TIMEOUT_MS / 1000, # Convert to seconds
timeout=self._polling_timeput_ms / 1000, # Convert to seconds
)
response.raise_for_status()
return response
except httpx.TimeoutException as err:
raise TimeoutError(f"Polling timeout after {POLLING_TIMEOUT_MS}ms") from err
raise TimeoutError(
f"Polling timeout after {self._polling_timeput_ms}ms"
) from err
except Exception as err:
raise err

Expand Down
3 changes: 3 additions & 0 deletions python/retoolrpc/utils/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ class RetoolRPCConfig(NamedTuple):
# The optional polling interval in milliseconds. Defaults to 1000. Minimum is 100.
polling_interval_ms: Optional[int] = 1000

# The optional polling timeout in milliseconds. Defaults to 5000.
polling_timeout_ms: Optional[int] = 5000

# The optional UUID of the agent. Will be automatically generated by default.
agent_uuid: Optional[str] = None

Expand Down
1 change: 1 addition & 0 deletions python/scripts/example.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ async def run_rpc():
resource_id="resource-uuid", # replace with retool rpc resource id
environment_name="production",
polling_interval_ms=1000,
polling_timeout_ms=5000,
log_level="info",
)

Expand Down
1 change: 1 addition & 0 deletions python/tests/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ def rpc_agent():
environment_name=ENVIRONMENT_NAME,
agent_uuid=AGENT_UUID,
polling_interval_ms=1000,
polling_timeout_ms=5000,
version="0.0.1",
)
)
Expand Down

0 comments on commit ab47ab6

Please sign in to comment.