Replies: 1 comment 2 replies
-
|
Thanks for opening this discussion and taking the time to write up such a analysis of the caching system. You've identified some architectural problems that I've working on. Looking at the current tight coupling issues, I'm already in the process of refactoring the caching system in the following direction: Proposed Changes (In Progress)Problem AnalysisThe current Solution Direction: Registry Pattern with Self-Describing CachesI've already started implementing these changes and am working through the following approach: 1. Rs2Cache with Self-DescriptionI'm extending the existing public abstract class Rs2Cache<K, V> {
// Existing code...
public abstract CacheSerializer<K, V> getSerializer();
public abstract Set<CacheCapability> getCapabilities();
public void performAsyncUpdate() { /* optional override */ }
}
public enum CacheCapability {
PERSISTENCE_ENABLED,
ASYNC_UPDATE_REQUIRED,
SCENE_DEPENDENT,
PROFILE_SPECIFIC
}2. Implement Explicit Cache RegistryRather than automatic discovery, I'm implementing explicit registration for predictable behavior: @Singleton
public class CacheRegistry {
private final Map<String, Rs2Cache<?, ?>> caches = new LinkedHashMap<>();
@Inject
public CacheRegistry() {
// Explicit registration - maintains full control
register("skills", Rs2SkillCache.getInstance());
register("quests", Rs2QuestCache.getInstance());
register("varbits", Rs2VarbitCache.getInstance());
// Add new caches here - single point of registration
}
public Set<Rs2Cache<?, ?>> getCachesWithCapability(CacheCapability capability) {
return caches.values().stream()
.filter(cache -> cache.getCapabilities().contains(capability))
.collect(Collectors.toSet());
}
}3. Refactor Managers to Use CapabilitiesI'm eliminating hardcoded cache lists and switch statements: // Current problematic approach:
private static void loadPersistentCaches(String profileKey) {
// Manual enumeration of each cache type...
if (Rs2SkillCache.getCache().isPersistenceEnabled()) {
CacheSerializationManager.loadCache(Rs2SkillCache.getCache()...);
}
// Repeat for each cache type
}
// New capability-driven approach I'm implementing:
private static void loadPersistentCaches(String profileKey) {
Set<Rs2Cache<?, ?>> persistentCaches =
registry.getCachesWithCapability(PERSISTENCE_ENABLED);
for (Rs2Cache<?, ?> cache : persistentCaches) {
CacheSerializationManager.loadCache(cache, profileKey);
if (cache.getCapabilities().contains(ASYNC_UPDATE_REQUIRED)) {
CompletableFuture.runAsync(() -> cache.performAsyncUpdate());
}
}
}4. Generic Serialization ManagementI'm replacing the switch-statement-based serialization with polymorphic serializers: // Remove hardcoded switch statements in CacheSerializationManager
public static <K, V> void saveCache(Rs2Cache<K, V> cache, String profileKey) {
if (!cache.isPersistenceEnabled()) return;
CacheSerializer<K, V> serializer = cache.getSerializer();
String json = serializer.serialize(cache);
// Use cache.getConfigKey() instead of hardcoded strings
}Why This ApproachAvoiding Full AutomationI'm deliberately not using reflection-based auto-discovery because:
Benefits of Explicit Registration
Current ProgressI've already begun implementing:
My Expected Outcome
This approach maintains explicit control while eliminating the tight coupling and scaling issues in the current implementation. The refactoring is designed to leverage the existing solid foundation while addressing the architectural concerns you made and i also have already seen. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
I was working on a caching system for PoH and noticed how tightly coupled and implicit all of the requirements and implementations are.
The current implementation of Rs2CacheManager, CacheSerializationManager and any Rs2Cache class requires someone to remember all the steps that are necessary for integrating the new Rs2Cache into the manager. There's no compile-time enforcement that checks for "completeness". Some of the difficulties this causes are:
-...
I'll start by giving some examples:
Rs2CacheManager.java
CacheSerializationManager.java
I'd like to move towards a design structure where
Rs2CacheManagerandCacheSerializationManagerare less tightly coupled with all of the classes extendingRs2Cache. When a new Cache is designed it should automatically (or with the least effort possible) register to the Rs2CacheManager. I'll post a couple of questions that can help us work towards a better implementation of the caching system.Beta Was this translation helpful? Give feedback.
All reactions