Skip to main content

You are viewing Agora Docs forBetaproducts and features. Switch to Docs

Android
iOS
macOS
Web
Linux C++
Unity

Store channel metadata

The Signaling storage service enables you to store and share contextual channel data in your app, such as props, announcements, member lists, and relationship chains. When channel metadata is set, updated, or deleted, the SDK triggers a storage event notification. Other users in the channel receive this notification within 100ms and use the information according to your business logic.

Understand the tech

Use channel metadata to store and share channel level information such as room attributes, group announcements, and auction item price updates. A set of channel metadata for a specific channel facilitates business-level data storage and real-time notifications. Each channel has only one set of channel metadata, but each set may contain multiple metadata items. For relevant restrictions, refer to the API usage restrictions. Each metadata item has key, value, and revision properties.

Channel metadata is stored permanently in the Signaling database. The data persists even after a channel is destroyed. You must explicitly delete it to remove it from the database. This feature impacts your storage billing. Refer to Pricing for details.

The storage service is available for both message channels and stream channels. Use the channelType parameter in the storage event to determine the channel type.

Prerequisites

Ensure that you have integrated the Signaling SDK in your project and implemented the framework functionality from the SDK quickstart page.

Implement channel metadata storage

The section shows you how to implement channel metadata storage in your Signaling app.

Set channel metadata

To create a new metadata item for the channel, or to update the value of an existing item, call setChannelMetadata. This method creates a new item in the channel metadata if the specified key does not exist, or overwrites the associated value if a metadata item with the specified key already exists.

The following example saves a set of metadata items for a message channel named channel1. Signaling adds timestamp and authorUid information to each metadata item it stores.


_16
Metadata metadata = new Metadata();
_16
metadata.getItems().add(new MetadataItem("Quantity", "20"));
_16
metadata.getItems().add(new MetadataItem("Announcement", "Welcome to our shop!"));
_16
metadata.getItems().add(new MetadataItem("T-shirt", "100"));
_16
_16
mRtmClient.getStorage().setChannelMetadata("channel1", RtmChannelType.MESSAGE, metadata, new MetadataOptions(true, true), nullptr, new ResultCallback<Void>() {
_16
@Override
_16
public void onSuccess(Void responseInfo) {
_16
log(CALLBACK, "set channel metadata success");
_16
}
_16
_16
@Override
_16
public void onFailure(ErrorInfo errorInfo) {
_16
log(ERROR, errorInfo.toString());
_16
}
_16
});

The onSuccess callback notifies you of the successful completion of the storage operation. Additionally, Signaling triggers an onStorageEvent notification of event type UPDATE within 100 ms to inform other channel members.

Get channel metadata

To retrieve all metadata items associated with a specific channel, call getChannelMetadata by specifying the channel name and the channel type. Refer to the following example:


_15
mRtmClient.getStorage().getChannelMetadata("channel1", RtmChannelType.MESSAGE, new ResultCallback<Metadata>() {
_15
@Override
_15
public void onSuccess(Metadata data) {
_15
log(CALLBACK, "get channel metadata success");
_15
log(INFO, "metadata major revision: " + data.getMajorRevision());
_15
for (MetadataItem item : data.getItems()) {
_15
log(INFO, item.toString());
_15
}
_15
}
_15
_15
@Override
_15
public void onFailure(ErrorInfo errorInfo) {
_15
log(ERROR, errorInfo.toString());
_15
}
_15
});

Signaling SDK returns the following data structure:


_25
{
_25
majorRevision: 734874892,
_25
metadata:{
_25
{ key:"Quantity",
_25
value:"20",
_25
revision:734874888,
_25
updateTs:1688978391900,
_25
authorUid:"Tony"
_25
},
_25
{
_25
key:"Announcement",
_25
value:"Welcome to our Shop!",
_25
revision:734874333,
_25
updated:1688978391800,
_25
authorUid:"Tomas"
_25
},
_25
{
_25
key:"T-shirt",
_25
value:"100",
_25
revision:734874222,
_25
updated:168897839100,
_25
authorUid:"Adam"
_25
}
_25
}
_25
}

Update channel metadata

To modify existing metadata items for a specified channel, call updateChannelMetadata. If the metadata item does not exist, an error is returned. This method is useful for business scenarios that require permission control to create new metadata items. For example, consider the following scenarios:

  • In an e-commerce auction, only administrators or product owners are authorized to list new products and set new attributes, while bidders may only modify price attributes.
  • In a gaming environment, only the administrator may define permissions as room properties.

The following example updates the value of a metadata item:


_17
Metadata metadata = new Metadata();
_17
metadata.getItems().add(new MetadataItem("T-shirt", "299"));
_17
MetadataOptions options = new MetadataOptions()
_17
options.setRecordTs(true);
_17
options.setRecordUserId(true);
_17
_17
mRtmClient.getStorage().updateChannelMetadata("channel1", RtmChannelType.MESSAGE, metadata, options, "", new ResultCallback<Void>() {
_17
@Override
_17
public void onSuccess(Void responseInfo) {
_17
log(CALLBACK, "Channel metadata updated successfully");
_17
}
_17
_17
@Override
_17
public void onFailure(ErrorInfo errorInfo) {
_17
log(ERROR, errorInfo.toString());
_17
}
_17
});

The onSuccess callback notifies you of the successful completion of the storage operation. Additionally, Signaling triggers an onStorageEvent notification of event type UPDATE within 100 ms to inform other channel members.

Delete channel metadata

To delete metadata items that are no longer required, call removeChannelMetadata. Refer to the following sample code:


_16
Metadata metadata = new Metadata();
_16
MetadataItem announcement = new MetadataItem();
_16
announcement.setKey("Announcement");
_16
metadata.getItems().add(announcement);
_16
_16
mRtmClient.getStorage().removeChannelMetadata("channel1", RtmChannelType.MESSAGE, metadata, new MetadataOptions(false, false), "", new ResultCallback<Void>() {
_16
@Override
_16
public void onSuccess(Void responseInfo) {
_16
log(CALLBACK, "remove channel metadata success");
_16
}
_16
_16
@Override
_16
public void onFailure(ErrorInfo errorInfo) {
_16
log(ERROR, errorInfo.toString());
_16
}
_16
});

Setting the value for a metadata item that is being deleted has no effect.

The onSuccess callback notifies you of the successful completion of the storage operation. Additionally, Signaling triggers an onStorageEvent notification of event type UPDATE within 100 ms to inform other channel members.

To delete the entire set of metadata for a channel, do not specify any metadata items when calling removeChannelMetadata. Refer to the following sample code:


_12
Metadata metadata = new Metadata();
_12
mRtmClient.getStorage().removeChannelMetadata("channel1", RtmChannelType.MESSAGE, metadata, new MetadataOptions(true, true), "", new ResultCallback<Void>() {
_12
@Override
_12
public void onSuccess(Void responseInfo) {
_12
log(CALLBACK, "remove channel metadata success");
_12
}
_12
_12
@Override
_12
public void onFailure(ErrorInfo errorInfo) {
_12
log(ERROR, errorInfo.toString());
_12
}
_12
});

info

Once channel metadata is deleted, it cannot be recovered. If you need data restoration, back up the metadata before deleting it.

Receive storage event notifications

A storage event notification returns the StorageEvent data structure, which includes the RtmStorageEventType parameter.

To receive storage event notifications, implement an event listener. See event listeners for details. In addition, set the withMetadata parameter to true when subscribing to or joining a channel.

Event notification mode

Currently, Signaling only supports the full data update mode. This means that when user or channel metadata is updated, the data field in the event notification contains all the attribute data of the user or the channel.

Additional storage features

To help resolve issues arising from concurrent updates to storage, Signaling offers version control and locking features.

Version control

Signaling integrates compare-and-set (CAS) version control to manage metadata updates. CAS is a concurrency control mechanism to ensure that updates to a shared resource occur only if the resource is in an expected state. The mechanism works as follows:

  1. The client reads the current version of a data item.
  2. Before making an update, the client compares the current version with the last read version number.
  3. If the versions match, the client proceeds with the update and increments the version number. If they do not match, the update is aborted.

The following are some sample scenarios where CAS version control is useful:

  • In a bidding scenario, if multiple users bid on a product at the same time, the first bidder succeeds while others receive an error. Users obtain the latest price information to update their bids.

  • In a red envelope grabbing scenario, the red envelope may only be grabbed once. The first user succeeds, while the rest receive an error.

The CAS version control feature provides two independent version control parameters. Set one or more of these values according to the needs of your business scenario:

  • majorRevision parameter in the setMajorRevision method: Enable version number verification of the entire set of channel metadata.

  • revision parameter of a MetadataItem: Enable version number verification of a single metadata item.

When setting channel metadata, or a single channel metadata item, use the revision attribute to enable or disable version control as follows:

  • To disable CAS verification, use the default value of -1 for the revision parameter.

  • To enable CAS verification, set the majorRevision or the revision parameter to a positive integer. The SDK updates the corresponding value after successfully verifying the revision number. If the specified revision number does not match the latest revision number in the database, the SDK returns an error.

The following sample shows how to use majorRevision and revision to update channel metadata and a metadata item:


_20
Metadata metadata = new Metadata();
_20
metadata.setMajorRevision(734874892);
_20
metadata.getItems().add(new MetadataItem("Quantity", "30", 734874888));
_20
metadata.getItems().add(new MetadataItem("Announcement", "Welcome to our shop!"));
_20
metadata.getItems().add(new MetadataItem("T-shirt", "101", 734874222));
_20
MetadataOptions options = new MetadataOptions()
_20
options.setRecordTs(true);
_20
options.setRecordUserId(true);
_20
_20
mRtmClient.getStorage().updateChannelMetadata("channel1", RtmChannelType.MESSAGE, metadata, options, "", new ResultCallback<Void>() {
_20
@Override
_20
public void onSuccess(Void responseInfo) {
_20
log(CALLBACK, "update channel metadata success");
_20
}
_20
_20
@Override
_20
public void onFailure(ErrorInfo errorInfo) {
_20
log(ERROR, errorInfo.toString());
_20
}
_20
});

In this example, CAS verification for channel metadata and metadata items is enabled by setting majorRevision and revision parameters to positive integers. Upon receiving the update call request, Signaling first verifies the provided major revision number against the latest value in the database. If there's a mismatch, it returns an error; if the values match, Signaling verifies the revision number for each metadata item using a similar logic.

info

When using version control, monitor onStorageEvent notifications to retrieve updated values for majorRevision and revision to ensure that the latest revision values are used for subsequent operations.

Locks

Locks enable users to gain exclusive access to critical resources, resolving contention issues with shared resources. For instance, consider a scenario where only one administrator is allowed in a channel at a time, and only the administrator can manage channel metadata by setting, deleting, and modifying it.

Compared to CAS, which controls the version of channel metadata, locks offer a higher level of control. They determine whether a user has the authority to call the setChannelMetadata, updateChannelMetadata, and removeChannelMetadata interfaces. Without acquiring the lock, a user cannot perform operations on channel metadata.

The following code demonstrates using a lock to update channel metadata. The user calling updateChannelMetadata must acquire the lock first for the call to succeed.


_20
Metadata metadata = new Metadata();
_20
metadata.getItems().add(new MetadataItem("Quantity", "40"));
_20
metadata.getItems().add(new MetadataItem("Announcement", "Welcome to our Shop!"));
_20
metadata.getItems().add(new MetadataItem("T-shirt", "300"));
_20
MetadataOptions options = new MetadataOptions()
_20
options.setRecordTs(true);
_20
options.setRecordUserId(true);
_20
_20
String lockName = "manage";
_20
mRtmClient.getStorage().updateChannelMetadata("channel1", RtmChannelType.MESSAGE, metadata, options, lockName, new ResultCallback<Void>() {
_20
@Override
_20
public void onSuccess(Void responseInfo) {
_20
log(CALLBACK, "update channel metadata success");
_20
}
_20
_20
@Override
_20
public void onFailure(ErrorInfo errorInfo) {
_20
log(ERROR, errorInfo.toString());
_20
}
_20
});

For more information on setting, acquiring, releasing, revoking, and removing locks, see Locks.

Reference

This section contains content that completes the information on this page, or points you to documentation that explains other aspects to this product.

API reference

Signaling