oops updates asset cache
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
/// When sending mutiple assets, how many before we give the client a quaint little sending resources message
|
||||
#define ASSET_CACHE_TELL_CLIENT_AMOUNT 8
|
||||
|
||||
/// Base browse_rsc asset transport
|
||||
/datum/asset_transport
|
||||
var/name = "Simple browse_rsc asset transport"
|
||||
var/static/list/preload
|
||||
/// Don't mutate the filename of assets when sending via browse_rsc.
|
||||
/// This is to make it easier to debug issues with assets, and allow server operators to bypass issues that make it to production.
|
||||
/// If turning this on fixes asset issues, something isn't using get_asset_url and the asset isn't marked legacy, fix one of those.
|
||||
var/dont_mutate_filenames = FALSE
|
||||
|
||||
/// Called when the transport is loaded by the config controller, not called on the default transport unless it gets loaded by a config change.
|
||||
/datum/asset_transport/proc/Load()
|
||||
if (CONFIG_GET(flag/asset_simple_preload))
|
||||
for(var/client/C in GLOB.clients)
|
||||
addtimer(CALLBACK(src, .proc/send_assets_slow, C, preload), 1 SECONDS)
|
||||
|
||||
/// Initialize - Called when SSassets initializes.
|
||||
/datum/asset_transport/proc/Initialize(list/assets)
|
||||
preload = assets.Copy()
|
||||
if (!CONFIG_GET(flag/asset_simple_preload))
|
||||
return
|
||||
for(var/client/C in GLOB.clients)
|
||||
addtimer(CALLBACK(src, .proc/send_assets_slow, C, preload), 1 SECONDS)
|
||||
|
||||
|
||||
/// Register a browser asset with the asset cache system
|
||||
/// asset_name - the identifier of the asset
|
||||
/// asset - the actual asset file (or an asset_cache_item datum)
|
||||
/// returns a /datum/asset_cache_item.
|
||||
/// mutiple calls to register the same asset under the same asset_name return the same datum
|
||||
/datum/asset_transport/proc/register_asset(asset_name, asset)
|
||||
var/datum/asset_cache_item/ACI = asset
|
||||
if (!istype(ACI))
|
||||
ACI = new(asset_name, asset)
|
||||
if (!ACI || !ACI.hash)
|
||||
CRASH("ERROR: Invalid asset: [asset_name]:[asset]:[ACI]")
|
||||
if (SSassets.cache[asset_name])
|
||||
var/datum/asset_cache_item/OACI = SSassets.cache[asset_name]
|
||||
OACI.legacy = ACI.legacy = (ACI.legacy|OACI.legacy)
|
||||
OACI.namespace_parent = ACI.namespace_parent = (ACI.namespace_parent | OACI.namespace_parent)
|
||||
OACI.namespace = OACI.namespace || ACI.namespace
|
||||
if (OACI.hash != ACI.hash)
|
||||
var/error_msg = "ERROR: new asset added to the asset cache with the same name as another asset: [asset_name] existing asset hash: [OACI.hash] new asset hash:[ACI.hash]"
|
||||
stack_trace(error_msg)
|
||||
log_asset(error_msg)
|
||||
else
|
||||
if (length(ACI.namespace))
|
||||
return ACI
|
||||
return OACI
|
||||
|
||||
SSassets.cache[asset_name] = ACI
|
||||
return ACI
|
||||
|
||||
|
||||
/// Returns a url for a given asset.
|
||||
/// asset_name - Name of the asset.
|
||||
/// asset_cache_item - asset cache item datum for the asset, optional, overrides asset_name
|
||||
/datum/asset_transport/proc/get_asset_url(asset_name, datum/asset_cache_item/asset_cache_item)
|
||||
if (!istype(asset_cache_item))
|
||||
asset_cache_item = SSassets.cache[asset_name]
|
||||
// To ensure code that breaks on cdns breaks in local testing, we only
|
||||
// use the normal filename on legacy assets and name space assets.
|
||||
var/keep_local_name = dont_mutate_filenames \
|
||||
|| asset_cache_item.legacy \
|
||||
|| asset_cache_item.keep_local_name \
|
||||
|| (asset_cache_item.namespace && !asset_cache_item.namespace_parent)
|
||||
if (keep_local_name)
|
||||
return url_encode(asset_cache_item.name)
|
||||
return url_encode("asset.[asset_cache_item.hash][asset_cache_item.ext]")
|
||||
|
||||
|
||||
/// Sends a list of browser assets to a client
|
||||
/// client - a client or mob
|
||||
/// asset_list - A list of asset filenames to be sent to the client. Can optionally be assoicated with the asset's asset_cache_item datum.
|
||||
/// Returns TRUE if any assets were sent.
|
||||
/datum/asset_transport/proc/send_assets(client/client, list/asset_list)
|
||||
if (!istype(client))
|
||||
if (ismob(client))
|
||||
var/mob/M = client
|
||||
if (M.client)
|
||||
client = M.client
|
||||
else //no stacktrace because this will mainly happen because the client went away
|
||||
return
|
||||
else
|
||||
CRASH("Invalid argument: client: `[client]`")
|
||||
if (!islist(asset_list))
|
||||
asset_list = list(asset_list)
|
||||
var/list/unreceived = list()
|
||||
|
||||
for (var/asset_name in asset_list)
|
||||
var/datum/asset_cache_item/ACI = asset_list[asset_name]
|
||||
if (!istype(ACI) && !(ACI = SSassets.cache[asset_name]))
|
||||
log_asset("ERROR: can't send asset `[asset_name]`: unregistered or invalid state: `[ACI]`")
|
||||
continue
|
||||
var/asset_file = ACI.resource
|
||||
if (!asset_file)
|
||||
log_asset("ERROR: can't send asset `[asset_name]`: invalid registered resource: `[ACI.resource]`")
|
||||
continue
|
||||
|
||||
var/asset_hash = ACI.hash
|
||||
var/new_asset_name = asset_name
|
||||
var/keep_local_name = dont_mutate_filenames \
|
||||
|| ACI.legacy \
|
||||
|| ACI.keep_local_name \
|
||||
|| (ACI.namespace && !ACI.namespace_parent)
|
||||
if (!keep_local_name)
|
||||
new_asset_name = "asset.[ACI.hash][ACI.ext]"
|
||||
if (client.sent_assets[new_asset_name] == asset_hash)
|
||||
if (GLOB.Debug2)
|
||||
log_asset("DEBUG: Skipping send of `[asset_name]` (as `[new_asset_name]`) for `[client]` because it already exists in the client's sent_assets list")
|
||||
continue
|
||||
unreceived[asset_name] = ACI
|
||||
|
||||
if (unreceived.len)
|
||||
if (unreceived.len >= ASSET_CACHE_TELL_CLIENT_AMOUNT)
|
||||
to_chat(client, "Sending Resources...")
|
||||
|
||||
for (var/asset_name in unreceived)
|
||||
var/new_asset_name = asset_name
|
||||
var/datum/asset_cache_item/ACI = unreceived[asset_name]
|
||||
var/keep_local_name = dont_mutate_filenames \
|
||||
|| ACI.legacy \
|
||||
|| ACI.keep_local_name \
|
||||
|| (ACI.namespace && !ACI.namespace_parent)
|
||||
if (!keep_local_name)
|
||||
new_asset_name = "asset.[ACI.hash][ACI.ext]"
|
||||
log_asset("Sending asset `[asset_name]` to client `[client]` as `[new_asset_name]`")
|
||||
client << browse_rsc(ACI.resource, new_asset_name)
|
||||
|
||||
client.sent_assets[new_asset_name] = ACI.hash
|
||||
|
||||
addtimer(CALLBACK(client, /client/proc/asset_cache_update_json), 1 SECONDS, TIMER_UNIQUE|TIMER_OVERRIDE)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
|
||||
/// Precache files without clogging up the browse() queue, used for passively sending files on connection start.
|
||||
/datum/asset_transport/proc/send_assets_slow(client/client, list/files, filerate = 3)
|
||||
var/startingfilerate = filerate
|
||||
for (var/file in files)
|
||||
if (!client)
|
||||
break
|
||||
if (send_assets(client, file))
|
||||
if (!(--filerate))
|
||||
filerate = startingfilerate
|
||||
client.browse_queue_flush()
|
||||
stoplag(0) //queuing calls like this too quickly can cause issues in some client versions
|
||||
|
||||
/// Check the config is valid to load this transport
|
||||
/// Returns TRUE or FALSE
|
||||
/datum/asset_transport/proc/validate_config(log = TRUE)
|
||||
return TRUE
|
||||
@@ -0,0 +1,87 @@
|
||||
/// CDN Webroot asset transport.
|
||||
/datum/asset_transport/webroot
|
||||
name = "CDN Webroot asset transport"
|
||||
|
||||
/datum/asset_transport/webroot/Load()
|
||||
if (validate_config(log = FALSE))
|
||||
load_existing_assets()
|
||||
|
||||
/// Processes thru any assets that were registered before we were loaded as a transport.
|
||||
/datum/asset_transport/webroot/proc/load_existing_assets()
|
||||
for (var/asset_name in SSassets.cache)
|
||||
var/datum/asset_cache_item/ACI = SSassets.cache[asset_name]
|
||||
save_asset_to_webroot(ACI)
|
||||
|
||||
/// Register a browser asset with the asset cache system
|
||||
/// We also save it to the CDN webroot at this step instead of waiting for send_assets()
|
||||
/// asset_name - the identifier of the asset
|
||||
/// asset - the actual asset file or an asset_cache_item datum.
|
||||
/datum/asset_transport/webroot/register_asset(asset_name, asset)
|
||||
. = ..()
|
||||
var/datum/asset_cache_item/ACI = .
|
||||
|
||||
if (istype(ACI) && ACI.hash)
|
||||
save_asset_to_webroot(ACI)
|
||||
|
||||
/// Saves the asset to the webroot taking into account namespaces and hashes.
|
||||
/datum/asset_transport/webroot/proc/save_asset_to_webroot(datum/asset_cache_item/ACI)
|
||||
var/webroot = CONFIG_GET(string/asset_cdn_webroot)
|
||||
var/newpath = "[webroot][get_asset_suffex(ACI)]"
|
||||
if (fexists(newpath))
|
||||
return
|
||||
if (fexists("[newpath].gz")) //its a common pattern in webhosting to save gzip'ed versions of text files and let the webserver serve them up as gzip compressed normal files, sometimes without keeping the original version.
|
||||
return
|
||||
return fcopy(ACI.resource, newpath)
|
||||
|
||||
/// Returns a url for a given asset.
|
||||
/// asset_name - Name of the asset.
|
||||
/// asset_cache_item - asset cache item datum for the asset, optional, overrides asset_name
|
||||
/datum/asset_transport/webroot/get_asset_url(asset_name, datum/asset_cache_item/asset_cache_item)
|
||||
if (!istype(asset_cache_item))
|
||||
asset_cache_item = SSassets.cache[asset_name]
|
||||
var/url = CONFIG_GET(string/asset_cdn_url) //config loading will handle making sure this ends in a /
|
||||
return "[url][get_asset_suffex(asset_cache_item)]"
|
||||
|
||||
/datum/asset_transport/webroot/proc/get_asset_suffex(datum/asset_cache_item/asset_cache_item)
|
||||
var/base = ""
|
||||
var/filename = "asset.[asset_cache_item.hash][asset_cache_item.ext]"
|
||||
if (length(asset_cache_item.namespace))
|
||||
base = "namespaces/[asset_cache_item.namespace]/"
|
||||
if (!asset_cache_item.namespace_parent)
|
||||
filename = "[asset_cache_item.name]"
|
||||
return base + filename
|
||||
|
||||
|
||||
/// webroot asset sending - does nothing unless passed legacy assets
|
||||
/datum/asset_transport/webroot/send_assets(client/client, list/asset_list)
|
||||
. = FALSE
|
||||
var/list/legacy_assets = list()
|
||||
if (!islist(asset_list))
|
||||
asset_list = list(asset_list)
|
||||
for (var/asset_name in asset_list)
|
||||
var/datum/asset_cache_item/ACI = asset_list[asset_name]
|
||||
if (!istype(ACI))
|
||||
ACI = SSassets.cache[asset_name]
|
||||
if (!ACI)
|
||||
legacy_assets += asset_name //pass it on to base send_assets so it can output an error
|
||||
continue
|
||||
if (ACI.legacy)
|
||||
legacy_assets[asset_name] = ACI
|
||||
if (length(legacy_assets))
|
||||
. = ..(client, legacy_assets)
|
||||
|
||||
|
||||
/// webroot slow asset sending - does nothing.
|
||||
/datum/asset_transport/webroot/send_assets_slow(client/client, list/files, filerate)
|
||||
return FALSE
|
||||
|
||||
/datum/asset_transport/webroot/validate_config(log = TRUE)
|
||||
if (!CONFIG_GET(string/asset_cdn_url))
|
||||
if (log)
|
||||
log_asset("ERROR: [type]: Invalid Config: ASSET_CDN_URL")
|
||||
return FALSE
|
||||
if (!CONFIG_GET(string/asset_cdn_webroot))
|
||||
if (log)
|
||||
log_asset("ERROR: [type]: Invalid Config: ASSET_CDN_WEBROOT")
|
||||
return FALSE
|
||||
return TRUE
|
||||
Reference in New Issue
Block a user