Box User Event: REST APIとPython
Box Platformでは、アプリケーションがサブスクライブできるイベントを公開します。これらのイベントは、標準ユーザーまたはサービスユーザーによって実行される処理に関連しています。
イベントは、User Event (単一のユーザーのセキュリティコンテキストでトリガーされるイベント) またはEnterprise Event (企業のコンテキスト内でユーザーまたはコンテンツに関連するイベント) 別にまとめられています。
この記事では、User Eventに重点を置いて説明します。
以下のさまざまなストリームタイプをサブスクライブできます。
all
— ユーザーに関するすべてのイベントchanges
— コンテンツの変更sync
— 同期対象フォルダに関連した変更
User Events
現在認証されているユーザーに関連する、低レイテンシのイベントストリームを提供します。
アプリケーションではこれを利用して、Boxアカウントに影響を与えた、アプリによる処理をユーザーに通知できます。
通常、/events
エンドポイントへのアクセスは次のようになります。
curl --location 'https://api.box.com/2.0/events?stream_type=all' \
--header 'Authorization: Bearer Q0...ZE'
以下が返されます。
{
"entries": [
{
"type": "event",
"event_id": "0a0dbedf101e537a6a1252924a7da9d966d91745",
"created_by": {
"type": "user",
"id": "18622116055",
"name": "Rui Barbosa",
"login": "..."
},
"created_at": "2023-06-20T06:58:26-07:00",
"recorded_at": "2023-06-20T06:58:27-07:00",
"event_type": "ITEM_CREATE",
"session_id": "37s0swhf516mcne1",
"source": {
"type": "folder",
"id": "213534631621",
...
}
}
],
"chunk_size": 1,
"next_stream_position": 30400984754258517
}
Python SDKを使用した同様のイベントクエリ:
def main():
"""
Simple script to demonstrate the use of events
"""
client = get_client(conf)
stream_position = 0
events = client.events().get_events(
limit=10,
stream_position=stream_position,
stream_type="all"
)
stream_position = events["next_stream_position"]
for event in events["entries"]:
print(
f"Got {event.event_type} on {event.created_at}: {event.source.type} {event.source.id} {event.source.name}"
)
この出力結果は以下のとおりです。
Got ITEM_UPLOAD on 2023-07-10T05:39:35-07:00: file 1256595598279 IMG_20190406_160049.jpg
Got ITEM_TRASH on 2023-07-10T05:40:27-07:00: file 1204688948039 Get Started with Box.pdf
Got ITEM_PREVIEW on 2023-07-10T05:40:41-07:00: file 1256595598279 IMG_20190406_160049.jpg
Got ITEM_TRASH on 2023-07-10T05:40:54-07:00: file 1256595598279 IMG_20190406_160049.jpg
Got ITEM_UNDELETE_VIA_TRASH on 2023-07-10T05:41:02-07:00: file 1204688948039 Get Started with Box.pdf
この呼び出しによってnext_stream_position
がどのように返されるかに注目してください。中断した場所から続行できるようにstream_position
として送り返すことができます。
Long Polling
User EventはLong pollingもサポートしています。つまり、接続が開いたままのAPIに対してget
を実行できます。イベントがトリガーされると、レスポンスが返されます。
ウェブソケット接続を開いていないことに注意してください。
これは2つのステップからなるプロセスです。
まず、/events
エンドポイントに対してOPTIONS
リクエストを送信すると、Long pollingに必要なURLが返されます。
返されたURLに対してGET
を送信すると、イベントが送信されるまで接続は開いたままになります。以下に例を示します。
curl --location --request OPTIONS 'https://api.box.com/2.0/events' \
--header 'Authorization: Bearer D8...sF'
結果は次のとおりです。
{
"chunk_size": 1,
"entries": [
{
"type": "realtime_server",
"url": "https://2.realtime.services.box.net/subscribe?channel=b188ef734f6f71fa6c85&stream_type=all",
"ttl": "10",
"max_retries": "10",
"retry_timeout": 610
}
]
}
次に、返されたURLをGET
で取得します。
curl --location 'https://2.realtime.services.box.net/subscribe?channel=b188ef734f6f71fa6c85&stream_type=all' \
--header 'Authorization: D8...sF'
これで、イベントがトリガーされた後に次の結果が返されます。
{
"message": "new_change",
"source": "uesi"
}
ご覧のとおり、レスポンスには何も情報がありません。これは、何か新しいことが起こったことをクライアントに通知しているだけです。ここで、クライアントは、新しいイベントを取得するために、最新の既知のstream_position
を指定して/events
エンドポイントにクエリを実行する必要があります。
curl --location 'https://api.box.com/2.0/events?stream_type=all&stream_position=30400986485844810&limit=50' \
--header 'Authorization: Bearer D8...sF'
{
"entries": [
{
"type": "event",
"event_id": "4f68ef94037862ddaadb74ff33e8d2758cf9a131",
...
"source": {
"type": "file",
"id": "1256652018464",
}
},
{
"type": "event",
"event_id": "5fb318e46a7002104cb7db2223729b1b724ed294",
...
"source": {
"type": "file",
"id": "1256624574539",
}
}
],
"chunk_size": 2,
"next_stream_position": 30400986485908488
}
上記の例では、2つのファイルをごみ箱に移動しました。
この時点で、クライアントは、/events
エンドポイントにOPTIONS
を送信して新しいURLを取得し、そのURLにGET
を送信することでプロセスを再開し、新しいイベントを受け取るまで待機する必要があります。
{
"chunk_size": 1,
"entries": [
{
"type": "realtime_server",
"url": "https://2.realtime.services.box.net/subscribe?channel=b188ef734f6f71fa6c85&stream_type=all",
"ttl": "10",
"max_retries": "10",
"retry_timeout": 610
}
]
}
OPTIONS
のレスポンスにはttl
、max_retries
、retry_timeout
が含まれていることに注意してください。これらのいずれかが発生した場合は、アプリは再度OPTIONS
で開始する必要があります。
SDKを使用したLong polling
Box SDKのいずれかを使用すれば、実装はさらに簡単になります。
次のPythonスクリプトを考えてみましょう。
def main():
"""
Simple script to demonstrate the use of events
"""
client = get_client(conf)
print("Long polling for events...")
events = client.events().generate_events_with_long_polling()
for event in events:
print(
"\t",
event.created_at,
event.event_type,
event.source.type,
event.source.id,
event.source.name,
)
アプリの一部のファイルを削除すると、次のようになります。
Long polling for events...
2023-07-10T08:16:39-07:00 ITEM_TRASH file 1256624574539 IMG_20190406_160049.jpg
2023-07-10T08:16:38-07:00 ITEM_TRASH file 1256652018464 box-dev-logo (1).png
新しいOPTIONS
の送信と最新のストリーム位置の管理はすべて、SDKで行われることに注意してください。基本的に、generate_events_with_long_polling
メソッドでは、new_change
メッセージを受信するたびに次の一連のイベントをポーリングし続けるジェネレータが返されます。
その他の考慮事項
Boxでのイベントの保存は無期限ではありません。
User Eventの保存期間は2週間~2か月間で、その後、User Eventは削除されます。
このフィードでは、すべての結果を迅速に返すことを重視しています。つまり、Boxでは、イベントが順不同で複数回返される可能性があります。重複するイベントは、イベントIDで識別できます。
APIリクエストでUser Eventにフィルタをかけることはできませんが、Enterprise Eventではサポートされています。
この記事を楽しんでいただけたら、ぜひ [Clap] をクリックしてください。
質問がある場合は、この記事のコメント欄またはBoxのforum.box.com (英語のみ) に投稿してください。
上記の例は、こちらのGitHubリポジトリを使用して簡単に複製できます。
Box Platformの使用を開始する場合は、こちらのGitHubリポジトリにあるPythonアプリのテンプレートをご確認ください。