CoolFace
Apppublic

AK-21/Graphite-Industrial-Intelligence

sourceHugging Faceupdated 3mo agoView on Hugging Face
0likes
cache.js170 linesDownload Raw Back to upstash
1import { Redis } from "@upstash/redis";2import { Cache } from "../core/index.js";3import { entityKind, is } from "../../entity.js";4import { OriginalName, Table } from "../../index.js";5const getByTagScript = `6local tagsMapKey = KEYS[1] -- tags map key7local tag        = ARGV[1] -- tag8 9local compositeTableName = redis.call('HGET', tagsMapKey, tag)10if not compositeTableName then11  return nil12end13 14local value = redis.call('HGET', compositeTableName, tag)15return value16`;17const onMutateScript = `18local tagsMapKey = KEYS[1] -- tags map key19local tables     = {}      -- initialize tables array20local tags       = ARGV    -- tags array21 22for i = 2, #KEYS do23  tables[#tables + 1] = KEYS[i] -- add all keys except the first one to tables24end25 26if #tags > 0 then27  for _, tag in ipairs(tags) do28    if tag ~= nil and tag ~= '' then29      local compositeTableName = redis.call('HGET', tagsMapKey, tag)30      if compositeTableName then31        redis.call('HDEL', compositeTableName, tag)32      end33    end34  end35  redis.call('HDEL', tagsMapKey, unpack(tags))36end37 38local keysToDelete = {}39 40if #tables > 0 then41  local compositeTableNames = redis.call('SUNION', unpack(tables))42  for _, compositeTableName in ipairs(compositeTableNames) do43    keysToDelete[#keysToDelete + 1] = compositeTableName44  end45  for _, table in ipairs(tables) do46    keysToDelete[#keysToDelete + 1] = table47  end48  redis.call('DEL', unpack(keysToDelete))49end50`;51class UpstashCache extends Cache {52  constructor(redis, config, useGlobally) {53    super();54    this.redis = redis;55    this.useGlobally = useGlobally;56    this.internalConfig = this.toInternalConfig(config);57    this.luaScripts = {58      getByTagScript: this.redis.createScript(getByTagScript, { readonly: true }),59      onMutateScript: this.redis.createScript(onMutateScript)60    };61  }62  static [entityKind] = "UpstashCache";63  /**64   * Prefix for sets which denote the composite table names for each unique table65   *66   * Example: In the composite table set of "table1", you may find67   * `${compositeTablePrefix}table1,table2` and `${compositeTablePrefix}table1,table3`68   */69  static compositeTableSetPrefix = "__CTS__";70  /**71   * Prefix for hashes which map hash or tags to cache values72   */73  static compositeTablePrefix = "__CT__";74  /**75   * Key which holds the mapping of tags to composite table names76   *77   * Using this tagsMapKey, you can find the composite table name for a given tag78   * and get the cache value for that tag:79   *80   * ```ts81   * const compositeTable = redis.hget(tagsMapKey, 'tag1')82   * console.log(compositeTable) // `${compositeTablePrefix}table1,table2`83   *84   * const cachevalue = redis.hget(compositeTable, 'tag1')85   */86  static tagsMapKey = "__tagsMap__";87  /**88   * Queries whose auto invalidation is false aren't stored in their respective89   * composite table hashes because those hashes are deleted when a mutation90   * occurs on related tables.91   *92   * Instead, they are stored in a separate hash with the prefix93   * `__nonAutoInvalidate__` to prevent them from being deleted when a mutation94   */95  static nonAutoInvalidateTablePrefix = "__nonAutoInvalidate__";96  luaScripts;97  internalConfig;98  strategy() {99    return this.useGlobally ? "all" : "explicit";100  }101  toInternalConfig(config) {102    return config ? {103      seconds: config.ex,104      hexOptions: config.hexOptions105    } : {106      seconds: 1107    };108  }109  async get(key, tables, isTag = false, isAutoInvalidate) {110    if (!isAutoInvalidate) {111      const result2 = await this.redis.hget(UpstashCache.nonAutoInvalidateTablePrefix, key);112      return result2 === null ? void 0 : result2;113    }114    if (isTag) {115      const result2 = await this.luaScripts.getByTagScript.exec([UpstashCache.tagsMapKey], [key]);116      return result2 === null ? void 0 : result2;117    }118    const compositeKey = this.getCompositeKey(tables);119    const result = (await this.redis.hget(compositeKey, key)) ?? void 0;120    return result === null ? void 0 : result;121  }122  async put(key, response, tables, isTag = false, config) {123    const isAutoInvalidate = tables.length !== 0;124    const pipeline = this.redis.pipeline();125    const ttlSeconds = config && config.ex ? config.ex : this.internalConfig.seconds;126    const hexOptions = config && config.hexOptions ? config.hexOptions : this.internalConfig?.hexOptions;127    if (!isAutoInvalidate) {128      if (isTag) {129        pipeline.hset(UpstashCache.tagsMapKey, { [key]: UpstashCache.nonAutoInvalidateTablePrefix });130        pipeline.hexpire(UpstashCache.tagsMapKey, key, ttlSeconds, hexOptions);131      }132      pipeline.hset(UpstashCache.nonAutoInvalidateTablePrefix, { [key]: response });133      pipeline.hexpire(UpstashCache.nonAutoInvalidateTablePrefix, key, ttlSeconds, hexOptions);134      await pipeline.exec();135      return;136    }137    const compositeKey = this.getCompositeKey(tables);138    pipeline.hset(compositeKey, { [key]: response });139    pipeline.hexpire(compositeKey, key, ttlSeconds, hexOptions);140    if (isTag) {141      pipeline.hset(UpstashCache.tagsMapKey, { [key]: compositeKey });142      pipeline.hexpire(UpstashCache.tagsMapKey, key, ttlSeconds, hexOptions);143    }144    for (const table of tables) {145      pipeline.sadd(this.addTablePrefix(table), compositeKey);146    }147    await pipeline.exec();148  }149  async onMutate(params) {150    const tags = Array.isArray(params.tags) ? params.tags : params.tags ? [params.tags] : [];151    const tables = Array.isArray(params.tables) ? params.tables : params.tables ? [params.tables] : [];152    const tableNames = tables.map((table) => is(table, Table) ? table[OriginalName] : table);153    const compositeTableSets = tableNames.map((table) => this.addTablePrefix(table));154    await this.luaScripts.onMutateScript.exec([UpstashCache.tagsMapKey, ...compositeTableSets], tags);155  }156  addTablePrefix = (table) => `${UpstashCache.compositeTableSetPrefix}${table}`;157  getCompositeKey = (tables) => `${UpstashCache.compositeTablePrefix}${tables.sort().join(",")}`;158}159function upstashCache({ url, token, config, global = false }) {160  const redis = new Redis({161    url,162    token163  });164  return new UpstashCache(redis, config, global);165}166export {167  UpstashCache,168  upstashCache169};170//# sourceMappingURL=cache.js.map