Delphi DLL Requires Chilkat v11.5.0+
Delphi DLL
Box: Poll User Events and Save a Checkpoint
See more Box Examples
Poll the authenticated user event stream in bounded batches. The local JSON checkpoint keeps processed event IDs and the next stream position. This single-process demonstration logs events; a production worker should commit its business action, deduplication record, and cursor transactionally and prune old IDs.
See the Box API guide for setup and the complete workflow.
Chilkat Delphi DLL Downloads
var
success: Boolean;
curl: HCkHttpCurl;
state: HCkJsonObject;
files: HCkFileAccess;
statePath: PWideChar;
page: HCkJsonObject;
seenPath: HCkStringBuilder;
eventId: PWideChar;
nextPosition: PWideChar;
batch: Integer;
i: Integer;
count: Integer;
more: Boolean;
authorizedCommand1: HCkStringBuilder;
headerReplacement1: Integer;
begin
success := False;
// Requires Chilkat 11.5.0 or later and a previously unlocked Chilkat bundle.
// See Global Unlock Sample.
// Guide: Box API Guide.
success := False;
// Supply an unexpired token obtained with one of the Box authentication examples.
// A token represents a particular user or service account. IDs must be accessible to it.
curl := CkHttpCurl_Create();
CkHttpCurl_SetVar(curl,'access_token','BOX_ACCESS_TOKEN');
state := CkJsonObject_Create();
files := CkFileAccess_Create();
statePath := 'qa_data/box_events_state.json';
if (CkFileAccess_FileExists(files,statePath) = True) then
begin
success := CkJsonObject_LoadFile(state,statePath);
if (success <> True) then
begin
Memo1.Lines.Add(CkJsonObject__lastErrorText(state));
Exit;
end;
if (CkJsonObject_HasMember(state,'position') <> True) then
begin
Memo1.Lines.Add('Invalid checkpoint: position missing.');
Exit;
end;
end
else
begin
// "now" starts a new subscription. It deliberately skips historical events.
CkJsonObject_UpdateString(state,'position','now');
end;
CkHttpCurl_SetVar(curl,'position',CkJsonObject__stringOf(state,'position'));
page := CkJsonObject_Create();
seenPath := CkStringBuilder_Create();
batch := 0;
more := True;
while (more = True) and (batch < 20) do
begin
CkHttpCurl_ClearTargetOutput(curl,'*');
authorizedCommand1 := CkStringBuilder_Create();
CkStringBuilder_SetString(authorizedCommand1,'curl -X GET "https://api.box.com/2.0/events?stream_type=all&stream_position={{position}}&limit=100" -H "Authorization: Bearer {{access_token}}"');
headerReplacement1 := CkStringBuilder_Replace(authorizedCommand1,'{{access_token}}',CkHttpCurl__getVar(curl,'access_token'));
success := CkHttpCurl_DoYourThing(curl,CkStringBuilder__getAsString(authorizedCommand1));
if ((success <> True) or (CkHttpCurl_getStatusCode(curl) <> 200)) then
begin
Memo1.Lines.Add('Box request failed. HTTP status: ' + IntToStr(CkHttpCurl_getStatusCode(curl)));
Memo1.Lines.Add('Failure reason: ' + IntToStr(CkHttpCurl_getFailReason(curl)));
Memo1.Lines.Add(CkHttpCurl__responseBodyStr(curl));
Exit;
end;
success := CkHttpCurl_GetResponseJson(curl,page);
if (success <> True) then
begin
Memo1.Lines.Add(CkHttpCurl__lastErrorText(curl));
Exit;
end;
count := CkJsonObject_SizeOfArray(page,'entries');
i := 0;
while i < count do
begin
CkJsonObject_putI(page,i);
eventId := CkJsonObject__stringOf(page,'entries[i].event_id');
if (eventId = '') then
begin
Memo1.Lines.Add('Event without an event_id; checkpoint not advanced.');
Exit;
end;
CkStringBuilder_Clear(seenPath);
CkStringBuilder_Append(seenPath,'seen.');
CkStringBuilder_Append(seenPath,eventId);
if (CkJsonObject_HasMember(state,CkStringBuilder__getAsString(seenPath)) = False) then
begin
// Replace this logging with your idempotent business operation.
// Record success only after that operation succeeds.
Memo1.Lines.Add(eventId + ' ' + CkJsonObject__stringOf(page,'entries[i].event_type') + ' ' + CkJsonObject__stringOf(page,'entries[i].source.id'));
CkJsonObject_UpdateBool(state,CkStringBuilder__getAsString(seenPath),True);
end;
i := i + 1;
end;
nextPosition := CkJsonObject__stringOf(page,'next_stream_position');
if (nextPosition = '') then
begin
Memo1.Lines.Add('Missing next_stream_position; checkpoint not advanced.');
Exit;
end;
more := (count > 0) and (nextPosition <> CkHttpCurl__getVar(curl,'position'));
CkJsonObject_UpdateString(state,'position',nextPosition);
success := CkJsonObject_WriteFile(state,statePath);
if (success <> True) then
begin
Memo1.Lines.Add(CkJsonObject__lastErrorText(state));
Exit;
end;
CkHttpCurl_SetVar(curl,'position',nextPosition);
batch := batch + 1;
end;
Memo1.Lines.Add('Checkpoint saved. Run again later to continue polling.');
CkHttpCurl_Dispose(curl);
CkJsonObject_Dispose(state);
CkFileAccess_Dispose(files);
CkJsonObject_Dispose(page);
CkStringBuilder_Dispose(seenPath);
CkStringBuilder_Dispose(authorizedCommand1);