Class FDBMetaDataStore

  • All Implemented Interfaces:
    RecordMetaDataProvider

    @API(MAINTAINED)
    public class FDBMetaDataStore
    extends FDBStoreBase
    implements RecordMetaDataProvider
    Serialization of RecordMetaData into the database.

    Storing meta-data in the database allows for it to be updated atomically. All clients of the database will see the new version at the same time. If, on the other hand, meta-data is part of the application itself, it is possible that during deployment of a new version of the application some instances will have out-of-date meta-data.

    • Field Detail

      • CURRENT_KEY

        public static final Tuple CURRENT_KEY
      • HISTORY_KEY_PREFIX

        public static final Tuple HISTORY_KEY_PREFIX
      • OLD_FORMAT_KEY

        public static final Tuple OLD_FORMAT_KEY
    • Method Detail

      • setDependencies

        public void setDependencies​(@Nonnull
                                    Descriptors.FileDescriptor[] dependencies)
        Set dependencies upon which record descriptors may depend.
        Parameters:
        dependencies - array of descriptors that record descriptors might depend on
      • setEvolutionValidator

        public void setEvolutionValidator​(@Nonnull
                                          MetaDataEvolutionValidator evolutionValidator)
        Set the validator used when saving a new version of the meta-data to ensure the new meta-data is a valid evolution of the old meta-data. See getEvolutionValidator() for more details.

        Whenever the meta-data store, saves a new version of the meta-data (through, for example, saveRecordMetaData(RecordMetaDataProvider)), the existing meta-data from the store is read. The new and existing meta-data are then compared, and an error is thrown if the new meta-data is not a valid evolution of the existing meta-data. See MetaDataEvolutionValidator for more details on how the meta-data should be evolved.

        If one sets a local file descriptor, then this validator is also used to make sure that the local file descriptor is compatible with the file descriptor within the meta-data proto retrieved from the database.

        Parameters:
        evolutionValidator - the validator used to ensure the new meta-data is a valid evolution of the existing meta-data
        See Also:
        MetaDataEvolutionValidator
      • getExtensionRegistry

        @Nullable
        protected ExtensionRegistry getExtensionRegistry()
        Get the extension registry used when deserializing meta-data proto messages. By default, the extension registry will have only the extensions specified in "record_metadata_options.proto". Note that this differs from the empty extension registry.

        When the meta-data proto is built into a RecordMetaData object, extension options on fields specifying primary key and index information are ignored. However, options specifying each record's type are still processed, including information specifying the meta-data's union descriptor. As a result, if the provided registry does not at least register the (record).usage extension option, the RecordMetaData may fail to build with an error message indicating that no union descriptor was specified.

        Returns:
        the extension registry used when parsing meta-data
      • setExtensionRegistry

        public void setExtensionRegistry​(@Nullable
                                         ExtensionRegistry extensionRegistry)
        Set the extension registry used when deserializing meta-data proto messages. Note that if using Protobuf version 2, a null extension registry serves as a synonym for the empty extension registry, but in Protobuf version 3, a null extension registry can result in NullPointerExceptions when the meta-data proto is deserialized. Therefore, users who upgrade from proto2 to proto3 may need to adjust the registry they pass to the meta-data store through this function.
        Parameters:
        extensionRegistry - the extension registry used when parsing meta-data
      • setMaintainHistory

        public void setMaintainHistory​(boolean maintainHistory)
        Set whether this store keeps a record of older versions.
        Parameters:
        maintainHistory - true if this store should maintain a history
      • loadAndSetCurrent

        public CompletableFuture<RecordMetaDataProto.MetaData> loadAndSetCurrent​(boolean checkCache,
                                                                                 int currentVersion)
        Load current meta-data from store and set for getRecordMetaData.
        Parameters:
        checkCache - true if the cache should be checked first
        currentVersion - the version to load
        Returns:
        a future that completes with the Protobuf form of the meta-data
      • loadCurrentSerialized

        protected CompletableFuture<byte[]> loadCurrentSerialized()
      • preloadMetaData

        @Nonnull
        public CompletableFuture<Void> preloadMetaData​(@Nullable
                                                       RecordMetaDataProvider metaDataProvider)
        Prepare a meta-data store for use by loading any existing RecordMetaData or storing an initial seed from the given provider.
        Parameters:
        metaDataProvider - a provider for a seed meta-data to be used when this store is empty
        Returns:
        a future that is complete when this store is ready for use
      • saveRecordMetaData

        @API(MAINTAINED)
        public void saveRecordMetaData​(@Nonnull
                                       Descriptors.FileDescriptor fileDescriptor)
        Save the record meta-data into the meta-data store.

        If the given records descriptor is missing a union message, this method will automatically add one to the descriptor before saving the meta-data. If the meta-data store is currently empty, a default union descriptor will be added to the meta-data based on the non-NESTED record types. Otherwise, it will update the records descriptor of the currently stored meta-data (see updateRecords(Descriptors.FileDescriptor)). The new union descriptor will include any type in existing union and any new record type in the new file descriptor. This method will process extension options.

        Parameters:
        fileDescriptor - the file descriptor of the record meta-data
        See Also:
        MetaDataProtoEditor.addDefaultUnionIfMissing(Descriptors.FileDescriptor)
      • saveRecordMetaData

        public void saveRecordMetaData​(@Nonnull
                                       RecordMetaDataProvider metaDataProvider)
        Save the record meta-data into the meta-data store.
        Parameters:
        metaDataProvider - the meta-data provider
      • saveRecordMetaData

        public void saveRecordMetaData​(@Nonnull
                                       RecordMetaDataProto.MetaData metaDataProto)
        Save the record meta-data into the meta-data store.
        Parameters:
        metaDataProto - the serialized record meta-data
      • saveRecordMetaDataAsync

        @API(MAINTAINED)
        public CompletableFuture<Void> saveRecordMetaDataAsync​(@Nonnull
                                                               Descriptors.FileDescriptor fileDescriptor)
        Save the record meta-data into the meta-data store.

        If the given records descriptor is missing a union message, this method will automatically add one to the descriptor before saving the meta-data. If the meta-data store is currently empty, a default union descriptor will be added to the meta-data based on the non-NESTED record types. Otherwise, it will update the records descriptor of the currently stored meta-data (see updateRecords(Descriptors.FileDescriptor)). The new union descriptor will include any type in existing union and any new record type in the new file descriptor. This method will process extension options. Also the records descriptor of the meta-data will change while generating the union.

        Parameters:
        fileDescriptor - the file descriptor of the record meta-data
        Returns:
        a future when save is completed
        See Also:
        MetaDataProtoEditor.addDefaultUnionIfMissing(Descriptors.FileDescriptor)
      • addIndex

        public void addIndex​(@Nonnull
                             String recordType,
                             @Nonnull
                             String indexName,
                             @Nonnull
                             String fieldName)
        Add a new index to the record meta-data.
        Parameters:
        recordType - the name of the record type
        indexName - the name of the new index
        fieldName - the field to be indexed
      • addIndex

        public void addIndex​(@Nonnull
                             String recordType,
                             @Nonnull
                             String indexName,
                             @Nonnull
                             KeyExpression indexExpression)
        Add a new index to the record meta-data.
        Parameters:
        recordType - the name of the record type
        indexName - the name of the new index
        indexExpression - the root expression of the index
      • addIndex

        public void addIndex​(@Nonnull
                             String recordType,
                             @Nonnull
                             Index index)
        Add a new index to the record meta-data.
        Parameters:
        recordType - the name of the record type
        index - the new index to be added
      • addIndexAsync

        @Nonnull
        public CompletableFuture<Void> addIndexAsync​(@Nonnull
                                                     String recordType,
                                                     @Nonnull
                                                     String indexName,
                                                     @Nonnull
                                                     String fieldName)
        Add a new index to the record meta-data asynchronously.
        Parameters:
        recordType - the name of the record type
        indexName - the name of the new index
        fieldName - the field to be indexed
        Returns:
        a future that completes when the index is added
      • addIndexAsync

        @Nonnull
        public CompletableFuture<Void> addIndexAsync​(@Nonnull
                                                     String recordType,
                                                     @Nonnull
                                                     String indexName,
                                                     @Nonnull
                                                     KeyExpression indexExpression)
        Add a new index to the record meta-data asynchronously.
        Parameters:
        recordType - the name of the record type
        indexName - the name of the new index
        indexExpression - the root expression of the index
        Returns:
        a future that completes when the index is added
      • addIndexAsync

        @Nonnull
        public CompletableFuture<Void> addIndexAsync​(@Nonnull
                                                     String recordType,
                                                     @Nonnull
                                                     Index index)
        Add a new index to the record meta-data asynchronously.
        Parameters:
        recordType - the name of the record type
        index - the index to be added
        Returns:
        a future that completes when the index is added
      • addMultiTypeIndex

        public void addMultiTypeIndex​(@Nullable
                                      List<String> recordTypes,
                                      @Nonnull
                                      Index index)
        Add a new index to the record meta-data that contains multiple record types. If the list is null or empty, the resulting index will include all record types. If the list has one element it will just be a normal single record type index.
        Parameters:
        recordTypes - a list of record types that the index will include
        index - the index to be added
      • addMultiTypeIndexAsync

        @Nonnull
        public CompletableFuture<Void> addMultiTypeIndexAsync​(@Nullable
                                                              List<String> recordTypes,
                                                              @Nonnull
                                                              Index index)
        Add a new index to the record meta-data that contains multiple record types asynchronously. If the list is null or empty, the resulting index will include all record types. If the list has one element it will just be a normal single record type index.
        Parameters:
        recordTypes - a list of record types that the index will include
        index - the index to be added
        Returns:
        a future that completes when the index is added
      • addUniversalIndex

        public void addUniversalIndex​(@Nonnull
                                      Index index)
        Add a new index on all record types.
        Parameters:
        index - the index to be added
      • addUniversalIndexAsync

        @Nonnull
        public CompletableFuture<Void> addUniversalIndexAsync​(@Nonnull
                                                              Index index)
        Add a new index on all record types.
        Parameters:
        index - the index to be added
        Returns:
        a future that completes when the index is added
      • dropIndex

        public void dropIndex​(@Nonnull
                              String indexName)
        Remove the given index from the record meta-data.
        Parameters:
        indexName - the name of the index to be removed
      • dropIndexAsync

        @Nonnull
        public CompletableFuture<Void> dropIndexAsync​(@Nonnull
                                                      String indexName)
        Remove the given index from the record meta-data asynchronously.
        Parameters:
        indexName - the name of the index to be removed
        Returns:
        a future that is complete when the index is dropped
      • updateRecords

        @API(MAINTAINED)
        public void updateRecords​(@Nonnull
                                  Descriptors.FileDescriptor recordsDescriptor)
        Update the meta-data records descriptor. This adds any new record types to the meta-data and replaces all of the current descriptors with the new descriptors.

        It is important to note that if a local file descriptor is set using setLocalFileDescriptor(Descriptors.FileDescriptor), the local file descriptor must be at least as evolved as the records descriptor passed to this method. Otherwise, updateRecords will fail.

        If the given file descriptor is missing a union message, this method will add one before updating the meta-data. The generated union descriptor is constructed by adding any non-NESTED types in the file descriptor to the union descriptor from the currently stored meta-data. A new field is not added if a field of the given type already exists, and the order of any existing fields is preserved. Note that types are identified by name, so renaming top-level message types may result in validation errors when trying to update the record descriptor. Also the records descriptor of the meta-data will change while generating the union.

        Parameters:
        recordsDescriptor - the new recordsDescriptor
      • updateRecordsAsync

        @Nonnull
        @API(MAINTAINED)
        public CompletableFuture<Void> updateRecordsAsync​(@Nonnull
                                                          Descriptors.FileDescriptor recordsDescriptor)
        Update the meta-data records descriptor asynchronously. This adds any new record types to the meta-data and replaces all of the current descriptors with the new descriptors.

        It is important to note that if a local file descriptor is set using setLocalFileDescriptor(Descriptors.FileDescriptor), the local file descriptor must be at least as evolved as the records descriptor passed to this method. Otherwise, updateRecordsAsync will fail.

        If the given file descriptor is missing a union message, this method will add one before updating the meta-data. The generated union descriptor is constructed by adding any non-NESTED types in the file descriptor to the union descriptor from the currently stored meta-data. A new field is not added if a field of the given type already exists, and the order of any existing fields is preserved. Note that types are identified by name, so renaming top-level message types may result in validation errors when trying to update the record descriptor.

        Parameters:
        recordsDescriptor - the new recordsDescriptor
        Returns:
        a future that completes when the records descriptor is updated
      • mutateMetaData

        public void mutateMetaData​(@Nonnull
                                   Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto)
        Mutate the stored meta-data proto using a mutation callback.

        This method applies the given mutation callback on the stored meta-data and then saves it back to the store. Callers might need to provide an appropriate MetaDataEvolutionValidator to the meta-data store, depending on the changes that the callback performs.

        Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database copy of a .proto file under source control.

        Parameters:
        mutateMetaDataProto - a callback that mutates the meta-data proto
      • mutateMetaData

        public void mutateMetaData​(@Nonnull
                                   Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto,
                                   @Nullable
                                   Consumer<RecordMetaDataBuilder> mutateRecordMetaDataBuilder)
        Mutate the stored meta-data proto and record meta-data builder using mutation callbacks.

        This method applies the given mutation callbacks on the stored meta-data and then saves it back to the store. Note the order that the callbacks are executed. mutateMetaDataProto is called first on the meta-data proto and then the second mutateRecordMetaDataBuilder is executed on the meta-data builder. Callers might need to provide an appropriate MetaDataEvolutionValidator to the meta-data store, depending on the changes that the callbacks perform.

        Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database copy of a .proto file under source control.

        Parameters:
        mutateMetaDataProto - a callback that mutates the meta-data proto
        mutateRecordMetaDataBuilder - a callback that mutates the record meta-data builder after the meta-data proto is mutated
      • mutateMetaDataAsync

        @Nonnull
        public CompletableFuture<Void> mutateMetaDataAsync​(@Nonnull
                                                           Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto)
        Mutate the stored meta-data proto using a mutation callback asynchronously.

        This method applies the given mutation callback on the stored meta-data and then saves it back to the store. Callers might need to provide an appropriate MetaDataEvolutionValidator to the meta-data store, depending on the changes that the callback performs.

        Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database copy of a .proto file under source control.

        Parameters:
        mutateMetaDataProto - a callback that mutates the meta-data proto
        Returns:
        a future that completes when the meta-data is mutated
      • mutateMetaDataAsync

        @Nonnull
        public CompletableFuture<Void> mutateMetaDataAsync​(@Nonnull
                                                           Consumer<RecordMetaDataProto.MetaData.Builder> mutateMetaDataProto,
                                                           @Nullable
                                                           Consumer<RecordMetaDataBuilder> mutateRecordMetaDataBuilder)
        Mutate the stored meta-data proto and record meta-data builder using mutation callbacks asynchronously.

        This method applies the given mutation callbacks on the stored meta-data and then saves it back to the store. Note the order that the callbacks are executed. mutateMetaDataProto is called first on the meta-data proto and then the second mutateRecordMetaDataBuilder is executed on the meta-data builder. Callers might need to provide an appropriate MetaDataEvolutionValidator to the meta-data store, depending on the changes that the callbacks perform.

        Also, callers must be cautious about modifying the stored records descriptor using mutation callbacks, as this will make the meta-data store the ultimate (and sole) source of truth for the record definitions and not just the in-database copy of a .proto file under source control.

        Parameters:
        mutateMetaDataProto - a callback that mutates the meta-data proto
        mutateRecordMetaDataBuilder - a callback that mutates the record meta-data builder after the meta-data proto is mutated
        Returns:
        a future that completes when the meta-data is mutated
      • updateStoreRecordVersions

        public void updateStoreRecordVersions​(boolean storeRecordVersions)
        Update whether record versions should be stored in the meta-data.
        Parameters:
        storeRecordVersions - whether record versions should be stored
      • updateStoreRecordVersionsAsync

        @Nonnull
        public CompletableFuture<Void> updateStoreRecordVersionsAsync​(boolean storeRecordVersions)
        Update whether record versions should be stored in the meta-data asynchronously.
        Parameters:
        storeRecordVersions - whether record versions should be stored
        Returns:
        a future that completes when storeRecordVersions is updated