package
1.2.18-prerelease02
Repository: https://github.com/uber/cadence.git
Documentation: pkg.go.dev

# README

What

This README explains how to add new Archiver implementations.

Steps

Step 1: Create a new package for your implementation

Create a new directory in the archiver folder. The structure should look like the following:

./common/archiver
  - filestore/                      -- Filestore implementation 
  - provider/
      - provider.go                 -- Provider of archiver instances
  - yourImplementation/
      - historyArchiver.go          -- HistoryArchiver implementation
      - historyArchiver_test.go     -- Unit tests for HistoryArchiver
      - visibilityArchiver.go       -- VisibilityArchiver implementations
      - visibilityArchiver_test.go  -- Unit tests for VisibilityArchiver

Step 2: Implement the HistoryArchiver interface

type HistoryArchiver interface {
	// Archive is used to archive a workflow history. When the context expires the method should stop trying to archive.
	// Implementors are free to archive however they want, including implementing retries of sub-operations. The URI defines
	// the resource that histories should be archived into. The implementor gets to determine how to interpret the URI.
	// The Archive method may or may not be automatically retried by the caller. The ArchiveOptions are used
	// to interact with these retries including giving the implementor the ability to cancel retries and record progress
  // between retry attempts. 
  // This method will be invoked after a workflow passes its retention period.
  // It's possible that this method will be invoked for one workflow multiple times and potentially concurrently,
  // implementation should correctly handle the workflow not exist case and return nil error.
    Archive(context.Context, URI, *ArchiveHistoryRequest, ...ArchiveOption) error
    
    // Get is used to access an archived history. When context expires method should stop trying to fetch history.
    // The URI identifies the resource from which history should be accessed and it is up to the implementor to interpret this URI.
    // This method should thrift errors - see filestore as an example.
    Get(context.Context, URI, *GetHistoryRequest) (*GetHistoryResponse, error)
    
    // ValidateURI is used to define what a valid URI for an implementation is.
    ValidateURI(URI) error
}

Step 3: Implement the VisibilityArchiver interface

type VisibilityArchiver interface {
    // Archive is used to archive one workflow visibility record. 
    // Check the Archive() method of the HistoryArchiver interface in Step 2 for parameters' meaning and requirements. 
    // The only difference is that the ArchiveOption parameter won't include an option for recording process. 
    // Please make sure your implementation is lossless. If any in-memory batching mechanism is used, then those batched records will be lost during server restarts. 
    // This method will be invoked when workflow closes. Note that because of conflict resolution, it is possible for a workflow to through the closing process multiple times, which means that this method can be invoked more than once after a workflow closes.
    Archive(context.Context, URI, *ArchiveVisibilityRequest, ...ArchiveOption) error
    
    // Query is used to retrieve archived visibility records. 
    // Check the Get() method of the HistoryArchiver interface in Step 2 for parameters' meaning and requirements.
    // The request includes a string field called query, which describes what kind of visibility records should be returned. For example, it can be some SQL-like syntax query string. 
    // Your implementation is responsible for parsing and validating the query, and also returning all visibility records that match the query. 
    // Currently the maximum context timeout passed into the method is 3 minutes, so it's ok if this method takes a long time to run.
    Query(context.Context, URI, *QueryVisibilityRequest) (*QueryVisibilityResponse, error)

    // ValidateURI is used to define what a valid URI for an implementation is.
    ValidateURI(URI) error
}

Step 4: Update provider to provide access to your implementation

Modify the ./provider/provider.go file so that the ArchiverProvider knows how to create an instance of your archiver. Also, add configs for you archiver to static yaml config files and modify the HistoryArchiverProvider and VisibilityArchiverProvider struct in the ../common/config.go accordingly.

FAQ

If my Archive method can automatically be retried by caller how can I record and access progress between retries?

ArchiverOptions is used to handle this. The following shows and example:

func (a *Archiver) Archive(
	ctx context.Context,
	URI string,
	request *ArchiveRequest,
	opts ...ArchiveOption,
) error {
  featureCatalog := GetFeatureCatalog(opts...) // this function is defined in options.go

  var progress progress

  // Check if the feature for recording progress is enabled.
  if featureCatalog.ProgressManager != nil {
    if err := featureCatalog.ProgressManager.LoadProgress(ctx, &prevProgress); err != nil {
      // log some error message and return error if needed.
    }
  }

  // Your archiver implementation...

  // Record current progress
  if featureCatalog.ProgressManager != nil {
    if err := featureCatalog.ProgressManager.RecordProgress(ctx, progress); err != nil {
      // log some error message and return error if needed. 
    }
  }
}

If my Archive method encounters an error which is non-retryable how do I indicate that the caller should not retry?

func (a *Archiver) Archive(
	ctx context.Context,
	URI string,
	request *ArchiveRequest,
	opts ...ArchiveOption,
) error {
  featureCatalog := GetFeatureCatalog(opts...) // this function is defined in options.go

  err := youArchiverImpl()
  if nonRetryableErr(err) {
    if featureCatalog.NonRetriableError != nil {
	  return featureCatalog.NonRetriableError() // when the caller gets this error type back it will not retry anymore.
    }
  }
}

How does my history archiver implementation read history?

The archiver package provides a utility class called HistoryIterator which is a wrapper of HistoryManager. Its usage is simpler than the HistoryManager given in the BootstrapContainer, so archiver implementations can choose to use it when reading workflow histories. See the historyIterator.go file for more details. Sample usage can be found in the filestore historyArchiver implementation.

Should my archiver define all its own error types?

Each archiver is free to define and return any errors it wants. However many common errors which exist between archivers are already defined in constants.go.

Is there a generic query syntax for visibility archiver?

Currently no. But this is something we plan to do in the future. As for now, try to make your syntax similar to the one used by our advanced list workflow API.

# Packages

Package filestore is a generated GoMock package.
No description provided by the author
Package s3store is a generated GoMock package.

# Functions

ConvertSearchAttrToBytes converts search attribute value from string back to byte array.
GetArchivingIncompleteHistoryOption returns an ArchiveOption so that archiver would archive incomplete history.
GetFeatureCatalog applies all the ArchiveOptions to the catalog and returns the catalog.
GetHeartbeatArchiveOption returns an ArchiveOption for enabling heartbeating.
GetNonRetriableErrorOption returns an ArchiveOption so that archiver knows what should be returned when an non-retryable error is encountered.
No description provided by the author
NewArchivalConfig constructs a new valid ArchivalConfig.
NewArchivalMetadata constructs a new ArchivalMetadata.
NewDisabledArchvialConfig returns a disabled ArchivalConfig.
NewHistoryIterator returns a new HistoryIterator.
NewHistoryIteratorFromState returns a new HistoryIterator with specified state.
NewJSONSizeEstimator returns a new SizeEstimator which uses json encoding to estimate size.
NewMockHistoryIterator creates a new mock instance.
NewMockSizeEstimator creates a new mock instance.
NewURI constructs a new archiver URI from string.
TagLoggerWithArchiveHistoryRequestAndURI tags logger with fields in the archive history request and the URI.
TagLoggerWithArchiveVisibilityRequestAndURI tags logger with fields in the archive visibility request and the URI.
ValidateGetRequest validates the get archived history request.
ValidateHistoryArchiveRequest validates the archive history request.
ValidateQueryRequest validates the query visibility request.
ValidateVisibilityArchivalRequest validates the archive visibility request.

# Constants

ArchivalDisabled means this cluster is not configured to handle archival.
ArchivalEnabled means this cluster is currently archiving.
ArchivalPaused means this cluster is configured to handle archival but is currently not archiving This state is not yet implemented, as of now ArchivalPaused is treated the same way as ArchivalDisabled.
ArchiveNonRetriableErrorMsg is the log message when the Archive() method encounters a non-retriable error.
ArchiveSkippedInfoMsg is the log messsage when the Archive() method encounter an entity not exists error.
ArchiveTransientErrorMsg is the log message when the Archive() method encounters a transient error.
ErrReasonConstructHistoryIterator is the error reason for failing to construct history iterator.
ErrReasonHistoryMutated is the error reason for mutated history.
ErrReasonInvalidArchiveRequest is the error reason for invalid archive request.
ErrReasonInvalidURI is the error reason for invalid URI.
ErrReasonReadHistory is the error reason for failing to read history.

# Variables

ErrContextTimeout is the error for context timeout.
ErrHistoryMutated is the error for mutated history.
ErrHistoryNotExist is the error for non-exist history.
ErrInvalidGetHistoryRequest is the error for invalid GetHistory request.
ErrInvalidQueryVisibilityRequest is the error for invalid Query Visibility request.
ErrInvalidURI is the error for invalid URI.
ErrNextPageTokenCorrupted is the error for corrupted GetHistory token.
ErrURISchemeMismatch is the error for mismatch between URI scheme and archiver.

# Structs

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
HistoryArchiverMock is an autogenerated mock type for the HistoryArchiver type.
No description provided by the author
No description provided by the author
No description provided by the author
MockArchivalMetadata is an autogenerated mock type for the ArchivalMetadata type.
MockHistoryIterator is a mock of HistoryIterator interface.
MockHistoryIteratorMockRecorder is the mock recorder for MockHistoryIterator.
MockSizeEstimator is a mock of SizeEstimator interface.
MockSizeEstimatorMockRecorder is the mock recorder for MockSizeEstimator.
No description provided by the author
No description provided by the author
VisibilityArchiverMock is an autogenerated mock type for the VisibilityArchiver type.
No description provided by the author

# Interfaces

No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author
No description provided by the author

# Type aliases

No description provided by the author
No description provided by the author
No description provided by the author