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

firestore: Implement Watch #4513

Closed
schmidt-sebastian opened this issue Dec 1, 2017 · 6 comments
Closed

firestore: Implement Watch #4513

schmidt-sebastian opened this issue Dec 1, 2017 · 6 comments
Assignees
Labels
api: firestore Issues related to the Firestore API. 🚨 This issue needs some love. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.

Comments

@schmidt-sebastian
Copy link

The Firestore Python client should gain the ability to receive realtime updates as outlined in the specification document.

Please take a look at Node: https://github.com/googleapis/nodejs-firestore/blob/master/src/watch.js
and Java: googleapis/google-cloud-java#2665

@dhermes dhermes added the api: firestore Issues related to the Firestore API. label Dec 1, 2017
@chemelnucfin chemelnucfin added the type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design. label Dec 4, 2017
@chemelnucfin
Copy link
Contributor

chemelnucfin commented Dec 17, 2017

@schmidt-sebastian @dhermes I started working on some translation from js, but not really sure how everything interacts, and there are some event handlers that I'm not sure how to convert from js to python without knowing more of the code. But anyway, feel free to take a look and let me know if this is just way over my head or if you are willing to help me get through it. I also looked at the java code which is implemented a bit differently than js. Also this is just very preliminary work....

chemelnucfin@57871e1

@chemelnucfin
Copy link
Contributor

@dhermes
So it looks like a basic producer consumer model, unless I'm missing something. I start a queue when I start a watch and block until I get an item in the queue then return it.

But the question I have is how do I tell grpc to send the ListenResponse to the queue that I have? Also, would it be better to have one queue per Watch instance or one queue per system?

Also seems to me that threads would be ok and I don't need multiprocessing?

@dhermes
Copy link
Contributor

dhermes commented Jan 5, 2018

@chemelnucfin I'm not very familiar with the feature. To start, which RPC does watch correspond to? (The only BIDI RPCs are Listen and Write and it seems Listen is a closer synonym to Watch)

A basic implementation would like like this:

import threading
import uuid

from six.moves import queue as queue_mod

from google.cloud import firestore


STOP = uuid.uuid4()


def make_request_gen(queue):
    while True:
        request = queue.get()  # Blocks "forever"
        if request == STOP:
            break

        yield request


def do_watch(queue, firestore_api):
    request_gen = make_requent_gen(queue)
    response_gen = firestore_api.listen(request_gen)

    for response in response_gen:
        do_something(response)

    queue.put(STOP)


client = firestore.Client()
firestore_api = client._firestore_api

queue = queue_mod.Queue()
thread = threading.Thread(
    target=do_watch, args=(queue, firestore_api), name='Meh')
thread.start()

Also seems to me that threads would be ok and I don't need multiprocessing?

I would leave it open so that users can specify which type of concurrency they want (with the above that would mean swapping out the queue and the thread for other primitives)

But the question I have is how do I tell grpc to send the ListenResponse to the queue that I have?

The

Also, would it be better to have one queue per Watch instance or one queue per system?

The queue is for your requests. It seems in many cases you'd only ever send a single initial ListenRequest so the queue is just a way for you to send STOP (which is actually necessary).

I don't think you'd need a queue for the ListenResponse messages that come in via response_gen, you just need a way to process them (i.e. do_something). But that is me speaking from ignorance of how the "watch" feature is supposed to work.

@chemelnucfin
Copy link
Contributor

Yes, it corresponds to listen.

So basically if I do the listen(request_gen), then grpc will send results into the queue whenever a change happens. ok, that's what I needed to know.

thanks.

@dhermes
Copy link
Contributor

dhermes commented Jan 5, 2018

.then grpc will send results into the queue whenever a change happens

No. The queue is owned by the caller to send requests. The only place ListenResponse-s get sent is into the response_gen iterator (it is an instance of the _Rendezvous god-class).

If you'd like to put them in a queue, that's where do_something comes in.

@chemelnucfin chemelnucfin self-assigned this Jan 15, 2018
@JustinBeckwith JustinBeckwith added the 🚨 This issue needs some love. label Jun 8, 2018
@tseaver
Copy link
Contributor

tseaver commented Jun 19, 2018

This is on the internal feature backlog.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api: firestore Issues related to the Firestore API. 🚨 This issue needs some love. type: feature request ‘Nice-to-have’ improvement, new feature or different behavior or design.
Projects
None yet
Development

No branches or pull requests

6 participants