Search
Loading...
Skip to content

Refresh Assets

Learn how to refresh asset sources when external changes occur outside CE.SDK in a server environment.

5 mins
estimated time
Download
StackBlitz
GitHub

CE.SDK automatically refreshes the asset library for built-in operations like uploads and deletions. However, when assets are modified outside of CE.SDK—through a custom CMS, cloud storage, or third-party upload widget—the asset source won’t reflect these changes automatically. Use engine.asset.assetSourceContentsChanged() to notify the engine and trigger a refresh.

This guide covers when manual refresh is needed, how to trigger refreshes programmatically, and integration patterns for server-side asset management.

When to Use Asset Refresh#

CE.SDK handles asset refresh automatically for built-in operations. Manual refresh is required when external systems modify asset source content.

Automatic refresh (no action needed):

  • Uploads using built-in sources like ly.img.upload.*
  • Deletions through default upload handlers
  • Modifications made through CE.SDK’s asset APIs

Manual refresh required:

  • External uploads via third-party services (Cloudinary, S3)
  • Backend modifications through CMS or API updates
  • Sync with external storage (Azure Blob, Google Cloud Storage)
  • Real-time collaboration when another process adds assets

Registering a Custom Asset Source#

Before refreshing assets, you need a custom asset source that fetches from your external system. The findAssets method queries your external data store each time assets are requested.

// Register a custom asset source that fetches from an external system
// This source will need manual refresh when external changes occur
engine.asset.addSource({
id: 'cloudinary-images',
async findAssets(queryData): Promise<AssetsQueryResult> {
// Fetch current assets from external data store
const filteredAssets = externalAssets.filter(
(asset) =>
!queryData.query ||
asset.name.toLowerCase().includes(queryData.query.toLowerCase())
);
return {
assets: filteredAssets.map((asset) => ({
id: asset.id,
label: asset.name,
meta: {
uri: asset.url,
thumbUri: asset.url,
blockType: '//ly.img.ubq/graphic'
}
})),
total: filteredAssets.length,
currentPage: queryData.page,
nextPage: undefined
};
}
});
console.log('✓ Created custom asset source: cloudinary-images');

This custom source fetches assets from an external data store (simulating Cloudinary, S3, or a CMS). When the external store changes, subsequent queries won’t reflect updates until you call assetSourceContentsChanged().

Refreshing After External Uploads#

When your backend receives new uploads from a third-party service, call assetSourceContentsChanged() to notify CE.SDK that the source contents have changed.

// Simulate an external upload (e.g., from Cloudinary upload widget)
// In a real application, this would be triggered by webhook or polling
const newAsset = {
id: 'cloud-3',
url: 'https://img.ly/static/ubq_samples/sample_3.jpg',
name: 'Forest Path'
};
externalAssets.push(newAsset);
// Notify CE.SDK that the source contents have changed
engine.asset.assetSourceContentsChanged('cloudinary-images');
console.log('✓ External upload complete, asset source refreshed');

The key is calling assetSourceContentsChanged('cloudinary-images') after the external upload completes. This tells CE.SDK to re-fetch assets on the next query.

Refreshing After External Modifications#

When your backend modifies asset metadata—renaming files, updating tags, or changing thumbnails—call assetSourceContentsChanged() to sync the asset source.

// Simulate backend modifications (e.g., CMS updates, API changes)
externalAssets[0] = {
...externalAssets[0],
name: 'Modified: Mountain Landscape'
};
// Refresh the asset library to reflect changes
engine.asset.assetSourceContentsChanged('cloudinary-images');
console.log('✓ External modification complete, asset source refreshed');

Any modification to assets in your external store requires a refresh. Without calling assetSourceContentsChanged(), subsequent queries may return stale data.

Refreshing After External Deletions#

When assets are deleted from your external system, call assetSourceContentsChanged() to ensure queries no longer return deleted assets.

// Simulate asset deletion from external system
const removed = externalAssets.pop();
console.log(`Removed asset from external store: ${removed?.name}`);
// Refresh the asset library to reflect the deletion
engine.asset.assetSourceContentsChanged('cloudinary-images');
console.log('✓ External deletion complete, asset source refreshed');

The refresh ensures deleted assets no longer appear in query results. If you skip this step, the engine may reference assets that no longer exist.

Integration Patterns#

Webhook Handler#

Handle webhooks from external services to trigger refreshes:

app.post('/webhooks/cloudinary', (req, res) => {
const { notification_type, public_id } = req.body;
if (notification_type === 'upload' || notification_type === 'delete') {
engine.asset.assetSourceContentsChanged('cloudinary-images');
}
res.status(200).send('OK');
});

Scheduled Sync#

For periodic synchronization with external systems:

import cron from 'node-cron';
cron.schedule('*/5 * * * *', () => {
// Refresh every 5 minutes
engine.asset.assetSourceContentsChanged('external-assets');
});

Event-Driven Updates#

Listen for database changes to trigger refreshes:

database.on('assets:changed', (sourceId) => {
engine.asset.assetSourceContentsChanged(sourceId);
});

Troubleshooting#

Assets not updating:

Verify the source ID passed to assetSourceContentsChanged() matches the ID used when registering the source with addSource(). Source IDs are case-sensitive.

Refresh not triggering:

Ensure you call assetSourceContentsChanged() after the external operation completes. If called before the upload finishes, findAssets() may return stale data.

Stale assets in queries:

Check that your findAssets implementation fetches fresh data on each call. Avoid caching responses unless you invalidate the cache when calling assetSourceContentsChanged().

Memory management:

Always dispose the engine when done processing to free resources. Use try/finally blocks to ensure cleanup happens even when errors occur.

API Reference#

MethodCategoryPurpose
engine.asset.assetSourceContentsChanged(sourceID)Asset APINotify engine that asset source contents changed
engine.asset.addSource(source)Asset APIRegister custom asset source
engine.asset.findAssets(sourceID, query)Asset APIQuery assets from a source