Build Custom Connector: Polling Trigger
When to use: periodic pulls from systems that don’t push events.
Manifest
"execution": { "type": "polling", "intervalMillis": 30000, "handlerBean": "poller" }
SDK
dispatcher.registerTriggerHandler("poller",
(c, cfg) -> Flux.interval(Duration.ofSeconds(30)).map(i -> Map.of("tick", i)));
dispatcher.startTrigger(manifest, "poll", ctx, Map.of());
If handlerBean is omitted, the dispatcher emits ticks by interval.
Full example (trigger)
Manifest (src/main/resources/manifests/orders.poller.json):
{
"schemaVersion": "1.0.0",
"id": "demo.orders.poller",
"version": "1.0.0",
"operations": { "pollNew": { "$ref": "#/operationDefs/pollNew" } },
"operationDefs": {
"pollNew": {
"operationId": "pollNew",
"kind": "trigger",
"inputSchema": { "type": "object" },
"outputSchema": { "type": "object" },
"execution": {
"type": "polling",
"intervalMillis": 60000,
"beanName": "ordersPoller"
}
}
}
}
Handler (OrdersPoller.java):
@Component("ordersPoller")
public class OrdersPoller implements ConnectorTriggerHandler<Map<String, Object>, Map<String, Object>> {
private final OrdersClient client;
public OrdersPoller(OrdersClient client) { this.client = client; }
@Override
public Flux<Map<String, Object>> trigger(ConnectorContext ctx, Map<String, Object> input) {
return Flux.defer(() -> {
String since = ctx.getState("lastSeenId", "0");
List<Order> newOrders = client.fetchSince(since);
String maxId = newOrders.stream().map(Order::id).max(String::compareTo).orElse(since);
ctx.setState("lastSeenId", maxId);
return Flux.fromIterable(newOrders)
.map(order -> Map.of(
"orderId", order.id(),
"tenantId", ctx.getTenantId(),
"total", order.total()));
});
}
}