MetaCacheEntryDef.java
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.doris.datasource.metacache;
import java.util.Objects;
import java.util.function.Function;
/**
* Immutable definition of a logical {@link MetaCacheEntry}.
*
* <p>This class only describes "what an entry is", not "entry runtime data".
* Runtime instances are still created by {@link AbstractExternalMetaCache}
* per catalog during {@code initCatalog(long)}.
*
* <p>A definition contains:
* <ul>
* <li>a stable logical name ({@link #name})</li>
* <li>declared key/value Java types ({@link #keyType}/{@link #valueType})</li>
* <li>a required miss loader ({@link #loader})</li>
* <li>default cache spec ({@link #defaultCacheSpec}) used when catalog params are absent</li>
* <li>whether refresh-after-write is enabled ({@link #autoRefresh})</li>
* </ul>
*
* <p>Use case 1: load-on-miss entry (recommended for table/object metadata).
* <pre>{@code
* private final MetaCacheEntryDef<NameMapping, IcebergTableCacheValue> tableEntryDef =
* MetaCacheEntryDef.of(
* "table",
* NameMapping.class,
* IcebergTableCacheValue.class,
* this::loadTableCacheValue,
* DEFAULT_ENTRY_CACHE_SPEC);
*
* registerMetaCacheEntryDef(tableEntryDef);
* }</pre>
*/
public final class MetaCacheEntryDef<K, V> {
/**
* Logical entry name inside one engine.
*
* <p>It is used as:
* <ul>
* <li>the lookup key in catalog entry groups</li>
* <li>the identity in stats output and error messages</li>
* </ul>
*
* <p>Constraint: must be unique inside one concrete external meta cache
* implementation (for example inside one IcebergExternalMetaCache).
*/
private final String name;
/**
* Declared key type of this entry.
*
* <p>Used by {@link AbstractExternalMetaCache} to validate that callers use
* the expected key class when obtaining the entry via
* {@code entry(catalogId, def)}.
*/
private final Class<K> keyType;
/**
* Declared value type of this entry.
*
* <p>Used by {@link AbstractExternalMetaCache} to validate value type
* compatibility for the requested entry and to prevent cross-entry misuse.
*/
private final Class<V> valueType;
/**
* Loader function used by {@link MetaCacheEntry#get(Object)}.
*
* <p>Cache miss triggers loader invocation. Loader is bound once at
* definition creation time and reused by all per-catalog runtime entries.
*/
private final Function<K, V> loader;
/**
* Default cache spec of this entry definition.
*
* <p>This value is used as fallback when no catalog-level override is provided.
* Keeping it on the definition makes each entry's default policy explicit.
*/
private final CacheSpec defaultCacheSpec;
private final boolean autoRefresh;
private MetaCacheEntryDef(String name, Class<K> keyType, Class<V> valueType,
Function<K, V> loader, CacheSpec defaultCacheSpec, boolean autoRefresh) {
this.name = Objects.requireNonNull(name, "entry name is required");
this.keyType = Objects.requireNonNull(keyType, "entry key type is required");
this.valueType = Objects.requireNonNull(valueType, "entry value type is required");
this.loader = Objects.requireNonNull(loader, "entry loader is required");
this.defaultCacheSpec = Objects.requireNonNull(defaultCacheSpec, "entry default cache spec is required");
this.autoRefresh = autoRefresh;
}
/**
* Create an entry definition with miss loader and an explicit default cache spec.
*
* @param name logical entry name, unique in one cache implementation
* @param keyType declared key class
* @param valueType declared value class
* @param loader miss loader invoked by {@link MetaCacheEntry#get(Object)}
* @param defaultCacheSpec default cache policy used by this entry definition
*/
public static <K, V> MetaCacheEntryDef<K, V> of(String name, Class<K> keyType, Class<V> valueType,
Function<K, V> loader, CacheSpec defaultCacheSpec) {
return new MetaCacheEntryDef<>(name, keyType, valueType, loader, defaultCacheSpec, true);
}
/**
* Create an entry definition with miss loader, explicit default cache spec and refresh policy.
*
* @param name logical entry name, unique in one cache implementation
* @param keyType declared key class
* @param valueType declared value class
* @param loader miss loader invoked by {@link MetaCacheEntry#get(Object)}
* @param defaultCacheSpec default cache policy used by this entry definition
* @param autoRefresh whether to enable refresh-after-write
*/
public static <K, V> MetaCacheEntryDef<K, V> of(String name, Class<K> keyType, Class<V> valueType,
Function<K, V> loader, CacheSpec defaultCacheSpec, boolean autoRefresh) {
return new MetaCacheEntryDef<>(name, keyType, valueType, loader, defaultCacheSpec, autoRefresh);
}
/**
* @return logical entry name.
*/
public String getName() {
return name;
}
/**
* @return declared key class.
*/
public Class<K> getKeyType() {
return keyType;
}
/**
* @return declared value class.
*/
public Class<V> getValueType() {
return valueType;
}
/**
* @return loader function.
*/
public Function<K, V> getLoader() {
return loader;
}
/**
* @return default cache spec of this entry definition.
*/
public CacheSpec getDefaultCacheSpec() {
return defaultCacheSpec;
}
/**
* @return true when refresh-after-write is enabled.
*/
public boolean isAutoRefresh() {
return autoRefresh;
}
}