-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
MemoryArtifactStore for unit testing and ArtifactStore SPI Validation #3517
Conversation
Also add tests for sorting, skipping and limiting result
This ensure that we can get test coverage stats easily as those are by default only calculated for main sources. Also fix some missing type annotation warnings
Support for "all" view was removed with apache#3167
Validates that implicit join from subject record to limits is working
CouchDBRestStore would throw an AssertionError if there is a revision mismatch. So adapt the logic accordingly. That means that get should do a simple lookup without revision and let deserialization logic enforce revision check
- Add waits for views to be updated for query tests - Perform cleanup post each test
- With join support the `_id` of the `value` is the limit one - `doc` is null when no result for join
The subject/identity view has a check for sub document field. This may not be properly enforced as part of query and thus its possible that query result set is super set of actual result. Thus transformViewResult may recheck the view conditions and opt to omit the result instance if it does not match all the conditions
Stop gab measure till AttachmentStore PR is merged
This instance need not be created as put is possible with existing activationStore instance. Current mode poses problem with MemoryArtifactStore as 2 separate instance of stores do not share the same state.
- NamespaceBlacklistTests - This test performs a direct interaction with CouchDB along with a generic interaction via `authStore` instance. Hence it cannot work with any non CouchDB storage - SequenceMigrationTests - This test requires a running OW setup and hits it using wsk rest client and also does direct interaction. Such test cannot work with MemoryArtifactStore as 2 different store instance would not share same state. This should however work with other ArtifactStore implementations as it is not aware of CouchDB
This PR is now ready for review. In a separate branch travis run was done with default
1 2 test needed to be ignored for run involving MemoryArtifactStore. See commit notes for details |
@@ -28,3 +28,9 @@ case class DocumentTypeMismatchException(message: String) extends ArtifactStoreE | |||
case class DocumentUnreadable(message: String) extends ArtifactStoreException(message) | |||
|
|||
case class PutException(message: String) extends ArtifactStoreException(message) | |||
|
|||
sealed abstract class ArtifactStoreRuntimeException(message: String) extends RuntimeException(message) | |||
|
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.
Is this sealed class intended to restrict exceptions for views only vs documents?
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.
Made it sealed
to follow the pattern used with ArtifactStoreException
i.e. a base RuntimeException
which can be used to indicate logical errors in code flow. So can be used for both views and document
import whisk.core.entity._ | ||
|
||
trait ArtifactStoreWhisksQueryBehaviors extends ArtifactStoreBehaviorBase { | ||
this: FlatSpec => |
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.
why not just extend?
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.
Makes sense. Modified the code to extend FlatSpec
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
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.
can you add a java/scala doc (comment) explaining the purpose of the view mapper.
do you anticipate this will be used outside of testing (in which case should this move to the tests package)?
import scala.reflect.ClassTag | ||
import scala.util.Try | ||
|
||
object MemoryArtifactStoreProvider extends ArtifactStoreProvider { |
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.
can you add a java/scala doc (comment) explaining the purpose of memory store provider; furthermore, do you anticipate this will be used outside of testing (in which case should this move to the tests package)?
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.
Would add docs. So far no concrete usecase to use them outside testing. One major reason to put them in main codebase was getting coverage data easily.
Typically Code Coverage data is only calculated for production code but here I would like to track coverage of Memory store implementation logic such that it can be ensured that tests cover all aspects of the implementation
private val triggerFields = commonFields | ||
|
||
protected val supportedTables = Set( | ||
"whisks.v2.1.0/actions", |
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.
should these be parameterized on the view versions?
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.
You mean have a separate variable for version and refer to that in name? That can be done
Here I wanted to explicitly list the actual version which current implementation is coded for. If any change in version is done in CouchDB views and config in application.conf updated this hardcoding would ensure that we take a conscious update here and ensure that implementations logic is adapted for newer version
@dubee @csantanapr @markusthoemmes 🙏 a pg to be safe although I expect Travis to be sufficient. |
@rabbah Currently there is a ignored test
In above curl for same setup if I remove
Should I create separate issue to track this? |
PG2 3021 🔵 |
@markusthoemmes If the PG test has passed can this PR be approved and merged? |
Opened #3560 to track this |
…apache#3517) Provides MemoryArtifactStore as an in-memory ArtifactStore implementation which can be used for unit testing and ArtifactStore SPI contract validation. CouchDB views determine which fields are included in returned document as part of query results. For non CouchDB cases this field list is defined by fieldsRequiredForView. ArtifactStore implementations can use it for projecting which fields should be included. CouchDB supports joins which is used for subject queries to fetch the limits. Most other NoSQL dbs do not support such joins. So for such cases transformViewResult can be used which would be responsible for performing the join. For it to work the ArtifactStore needs to provide an implementation of DocumentProvider which returns the raw json for a provided doc id. The MemoryViewMapper is an ArtifactStore implementation specific abstraction which converts the query keys passed to query to underlying storage query syntax. Each store implementation needs to have similar logic implemented to cover all possible scenarios from all the active views. Here the test suite plays an important role by validating that all query cases are covered. The added test suites need to be kept in sync with any change in view logic or addition of new views. Then only it can be ensured that other ArtifactStore implementation cover all the use cases as supported by default CouchDB. So going forward MemoryArtifactStore would become a canonical implementation of ArtifactStore contract.
Provides an in-memory
ArtifactStore
implementation which can be used for unit testing andArtifactStore
SPI contract validation as proposed in #3387Description
This PR introduces a
MemoryArtifactStore
which stores the artifacts in an in-memory map and supports all operations as expected from anArtifactStore
.Test Suite
The PR also includes a test suite
ArtifactStoreBehavior
to validate theArtifactStore
SPI contract. This is broken down in following partsArtifactStoreCRUDBehaviors
- Checks normal CRUD operationsArtifactStoreQueryBehaviors
- Check the query contract around skipping, limiting, sorting etcArtifactStoreSubjectQueryBehaviors
- Check views specific toWhiskAuth
specially around the join support for limitsFor now these tests are run for 2 stores and passes for them
Design for Non CouchDB Stores
CouchDB performs queries based on computed views. Most other databases provide a query interface with backing indexes. Currently OpenWhisk logic provides the view name as part of
query
invocation and thus has an implicit dependency on CouchDB view support. This has following impact on any non CouchDB store implementationMapping views to queries
For database which support SQL like constructs we need to map the query as expressed in CouchDB view to SQL. For e.g. if we need to map
whisks.v2.1.0/actions
view to some queryThen it would be expressed as following pseudo query
Here
rootns
- Is a computed field created at time of creation (see below)exec
- Would be a computed field created at runtime during query result post processingSometimes its not possible to completely map the view condition to query. For e.g. in subject queries. In such cases query partially applies the condition and then in
DocumentHandler
full conditions are applied thus result returned from query may be a super set of actual result set and actual result is thus obtained via "filtering"Interpreting the keys
Query parameters
startKey
andendKey
are closely tied to view implementation. Thus any other store would need to interpret the values in keys as per the view name. To support that this PR introduces aDocumentHandler
trait which defines the db neutral operationsThere is a separate handle implementation provided for each entity i.e.
ActivationHandler
,WhisksHandler
andSubjectHandler
Sections below would provide more details on the various methods
Computed Keys -
computedFields
Some of the views in use make use of computed fields in the view logic. For e.g. view for rules computes a
root
namespace when namespace is a multi segment pathFor supporting such cases in non CouchDB store
DocumentHandler#computedFields
can be used. This would compute the required field at time ofput
which theArtifactStore
implementation can then persist along with the main document. For e.g. for Mongo case such a computed json object can be stored under a separate_computed
field internally.These computed fields can then be used for defining declarative indexes. For now following computed fields are generated
rootns
- Root name space.nspath
- Namespace with Entity path. The nspath is computed based on logic in whisks-filters.v2.1.0/activationsdeleteLogs
- This field is computed based on logic inlogCleanup/byDateWithLogs
i.e. flag would enabled for all such activations which are not sequenceSee Mongo ArtifactStore for more details and examples
Projected Fields -
fieldsRequiredForView
CouchDB views determine which all fields are included in returned document as part of query result. For non CouchDB cases this field list is defined by
fieldsRequiredForView
. ArtifactStore implementation can use it for projecting which all fields should be includedJoin Support -
transformViewResult
CouchDB supports joins which is used for subject queries to fetch the limits. Most other no sql db does not support such joins. So for such cases
transformViewResult
can be used which would be responsible for performing the join. For it to work theArtifactStore
need to provide an implementation ofDocumentProvider
which returns the raw json for provided idMemoryViewMapper
This is an
ArtifactStore
implementation specific abstraction which converts the query keys passed toquery
to underlying storage query syntax. Each store implementation needs to have similar logic implementated which cover all possible scenarios from all the active viewsHere the test suite plays an important role by validating that all query cases are covered.
TestSuite and future view changes
This test suite would need to be kept in sync with any change in view logic or addition of new views. Then only it can be ensured that other
ArtifactStore
implementation cover all the usecases as supported by default CouchDB. So going forwardMemoryArtifactStore
would become a cononical implementation ofArtifactStore
contract!Pending Work
namespaceThrottlings/blockedNamespaces
viewRelated issue and scope
My changes affect the following components
Types of changes
Checklist: