Skip to content
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

[ADDED] KeyValue and ObjectStore support for JetStream #832

Merged
merged 1 commit into from Oct 7, 2021
Merged

Conversation

derekcollison
Copy link
Member

@derekcollison derekcollison commented Sep 27, 2021

Also:

  • Fixed message reply in PublishMsgAsync
  • Ability to seal streams
  • Ability for consumer to get message headers only, no msg payload
  • GetLastMsg and purgeStream by subject

@coveralls
Copy link

coveralls commented Sep 27, 2021

Coverage Status

Coverage decreased (-1.9%) to 84.89% when pulling 141643a on kvo into 4e70dbe on main.

Copy link
Contributor

@ripienaar ripienaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good in general, a few comments of things the ADR covered and deviations on ADR design

js.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Show resolved Hide resolved
Copy link
Member

@aricart aricart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Part of the reason why KvEntry is OK is that it is effectively a StoredMessage, with additional metadata about the bucket and the operation. With that said, I would much rather have a presentation where such values are in the headers. But there we get into additional issues: headers from the system may collide with user headers, and if the user sets a header that collides what is the meaning of that.

For replication and watches, the understanding of DELETE as an operation is important. Empty is really open to interpretation. The store could a have value by simply indicating that the key exists, thus the need for the operation to be telegraphed.

Outside of applications that deal with replication or that need to do something special on delete, the absence of the value is simpler. For NGS, my KV wrappers actually hide all the unpacking and simply code DELETEs as a null return value (ie I don't differentiate). But In some cases for example where keys should have a TTL, it is important to know the value doesn't exist even if it did.

TBH - I would rather see the ADR extended to deal with blobs and perhaps provide a compare and swap based on value, but understand that this is not what the nats-server is doing.

kv.go Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
// Get returns the latest value for the key.
Get(key string) (value []byte, revision uint64, err error)
// Put will place the new value for the key into the store.
Put(key string, value []byte) (revision uint64, err error)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Put fail if the key doesn't exist? - IE looking for clarification between Create and Put wondering if what we are trying to accomplish here is some sort of compare and swap.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the ADR, there is no create, just put, and the behavior is create or replace

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would Init be more indicative than Create?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Create only succeeds if not present, Update only if it is present and has not changed, and Put just works all the time sans other issues.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe they should all have this functionality.

kv.go Outdated Show resolved Hide resolved
object.go Outdated Show resolved Hide resolved
object.go Outdated Show resolved Hide resolved
object.go Show resolved Hide resolved
object.go Outdated Show resolved Hide resolved
@ColinSullivan1
Copy link
Member

ColinSullivan1 commented Sep 27, 2021

With respect to the object store we should allow the design to support features (external or internal) such as:

Lifecycle Management (delete, TTL)
Event Notifications (add/delete/lock)
Locking
Archiving (tiered storage)
Searching/Indexing (tagging)
Versioning

With the proposed design it seems that all of this could be possible through an external system (primarily via object nomenclature) while keeping functionality as simple as possible here. Just want to avoid making it difficult to build a future feature due to a design decision today.

@derekcollison
Copy link
Member Author

derekcollison commented Sep 27, 2021

Lifecycle Management (delete, TTL)

  • We have TTL, but not explicit delete, can add though the delete.

Event Notifications (add/delete/lock)

  • We have these in general for streams (sans lock/seal). @ripienaar can confirm

Locking

  • I did a soft seal so to speak as we discussed. Would need for formalize to avoid deletes of messages, purges etc.
  • That can all be done now with perms but I think seal would be good eventually.

Archiving (tiered storage)

  • That is way bigger then just object stuff, that is a whole core JetStream thing.

Searching/Indexing (tagging)

  • Tagging maybe if we promote to stream itself.
  • Indexing feels external as we discussed.

Versioning

  • What do you mean here?

kv.go Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Show resolved Hide resolved
kv.go Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
@derekcollison
Copy link
Member Author

ok I pushed updates to KV. Will do small update to Object in a bit for versions and Purge as well, etc.

@kozlovic
Copy link
Member

kozlovic commented Oct 5, 2021

@derekcollison Following the PR with the FC fix, this PR has now conflict that will need to be addressed. We need to be careful in reverting your FC changes that we are not putting back the way it was prior to the FC fix PR :-)

kv.go Outdated Show resolved Hide resolved
}

// CreateObjectStore will create an object store.
func (js *js) CreateObjectStore(cfg *ObjectStoreConfig) (ObjectStore, error) {
Copy link
Member

@wallyqs wallyqs Oct 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think maybe we should update the interface to have the partial opts like:

Suggested change
func (js *js) CreateObjectStore(cfg *ObjectStoreConfig) (ObjectStore, error) {
func (js *js) CreateObjectStore(cfg *ObjectStoreConfig, opts ...JSOpt) (ObjectStore, error) {

so that later on can pass the arguments below for example like: js.AddStream(scfg, opts)
That would make it possible to change the timeout or context for example.
(This could be addressed in a different PR but before tagging the client to not break the interface)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't that duplicate what we inherit from the js receiver when you setup JetStream context originally?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of MaxWait it would override what was inherited from the default in the JS context, but for nats.Context option with a timeout for example, those generally passed via arguments like CreateObjectStore(cfg *ObjectStoreConfig, nats.Context(ctx))

kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
Copy link
Contributor

@ripienaar ripienaar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some general comments for the call today

object.go Outdated Show resolved Hide resolved
object.go Outdated Show resolved Hide resolved
object.go Outdated Show resolved Hide resolved
object.go Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
kv.go Outdated Show resolved Hide resolved
Also:
- Fixed message reply in PublishMsgAsync
- Ability to seal streams
- Ability for consumer to get message headers only, no msg payload
- GetLastMsg and purgeStream by subject

Signed-off-by: Derek Collison <derek@nats.io>
@kozlovic kozlovic changed the title First Pass at KeyValue and ObjectStore [ADDED] KeyValue and ObjectStore support for JetStream Oct 7, 2021
@kozlovic kozlovic merged commit 639c3d0 into main Oct 7, 2021
@kozlovic kozlovic deleted the kvo branch October 7, 2021 22:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants