-
Notifications
You must be signed in to change notification settings - Fork 278
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Introduces SchemaRegistry
and related classes
#8614
Conversation
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/AbstractSchemaProvider.java
Fixed
Show fixed
Hide fixed
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/AbstractSchemaProvider.java
Fixed
Show fixed
Hide fixed
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/AbstractSchemaProvider.java
Fixed
Show fixed
Hide fixed
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/AbstractSchemaProvider.java
Fixed
Show fixed
Hide fixed
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/AbstractSchemaProvider.java
Fixed
Show fixed
Hide fixed
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/AbstractSchemaProvider.java
Fixed
Show fixed
Hide fixed
SchemaRegistry
and related classes
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/AbstractSchemaProvider.java
Outdated
Show resolved
Hide resolved
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaRegistry.java
Outdated
Show resolved
Hide resolved
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaCache.java
Outdated
Show resolved
Hide resolved
public <T> T get(final SchemaId<T> schemaClass) { | ||
SchemaProvider<T> provider = (SchemaProvider<T>) providers.get(schemaClass); | ||
if (provider == null) { | ||
throw new IllegalArgumentException( | ||
"No provider registered for schema " | ||
+ schemaClass | ||
+ " or it does not support milestone " | ||
+ milestone); | ||
} | ||
T schema = cache.get(milestone, schemaClass); | ||
if (schema != null) { | ||
return schema; | ||
} | ||
final SpecMilestone effectiveMilestone = provider.getEffectiveMilestone(milestone); | ||
if (effectiveMilestone != milestone) { | ||
schema = cache.get(effectiveMilestone, schemaClass); | ||
if (schema != null) { | ||
cache.put(milestone, schemaClass, schema); | ||
return schema; | ||
} | ||
} | ||
schema = provider.getSchema(this); | ||
cache.put(effectiveMilestone, schemaClass, schema); | ||
if (effectiveMilestone != milestone) { | ||
cache.put(milestone, schemaClass, schema); | ||
} | ||
return schema; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We are relying on the fact that we are calling SchemaRegistryBuilder
from a "concurrency free" part of the code. I understand this is by design but maybe we can remove that assumption (so it does not bite us in the future).
Once the registry is primed, we should always hit the cache. However, it isn't thread-safe before priming.
What about separating the logic on get()
to only read the cache. If we attempt to call get()
w/o priming the registry first, we fail. We can move the logic that populates the cache to primeRegistry()
, and make it synchronized so we know it is thread-safe no matter where it is being called from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes I agree! Generally, a better separation between priming and lookup reflects the usage we expect.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Relooking at this, the separation can't be done.
The way this works is that, when the schema is being created, it can lookup in the registry itself so it may trigger a creation of a schema (dependency). This help us not dealing with ordering (it works as soon as there are no dependency loops).
The real point here is if we want or not a dependency loop detection. To me it can only happen if as a developer you pick the wrong schemaId (and it is compatible with the type you need in that moment). Let me think
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaCache.java
Outdated
Show resolved
Hide resolved
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaTypes.java
Outdated
Show resolved
Hide resolved
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/SchemaRegistry.java
Outdated
Show resolved
Hide resolved
dependency loop detection refactored package and visibility add comments for readability
|
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/AbstractSchemaProvider.java
Dismissed
Show dismissed
Hide dismissed
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/AbstractSchemaProvider.java
Dismissed
Show dismissed
Hide dismissed
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/AbstractSchemaProvider.java
Dismissed
Show dismissed
Hide dismissed
improves Builder checks
ethereum/spec/src/main/java/tech/pegasys/teku/spec/schemas/registry/AbstractSchemaProvider.java
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
…istry/AbstractSchemaProvider.java Mehdi's approach Co-authored-by: Mehdi AOUADI <[email protected]>
This PR introduces
SchemaTypes
that will hold the staticschemaId
s for all datastructres types (they won't be milestone dependant, we will have only one even if the schema will change along the different forks)SchemaRegistry
class andSchemaCache
responsible for implementing the registry with its internal cross-milestone cacheSchemaProvider
interface and a base abstract class which implements the rules for generating a schema (the actual schema instantiation for which milestone(s)) for a givenschemaId
.SchemaRegistryBuilder
will be responsible to build the schema registry for eachmilestone
viabuild
method.Note the design of the registry is based on the assumption that all registries will be built at startup (during
SpecVersion
creations) and registries will be immediately "primed". This guarantees that cache writes (put
s) will happen only during that phase, which is a single-threaded (non concurrent). This is why the cache is not dealing with any concurrency\synchronization. After initialization the cache will be "readonly".related to #8592
the full direction can be seen here: #8592
Documentation
doc-change-required
label to this PR if updates are required.Changelog