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

initial version of migration guide #121

Merged
merged 12 commits into from
Jul 11, 2019
Merged

initial version of migration guide #121

merged 12 commits into from
Jul 11, 2019

Conversation

cguardia
Copy link
Contributor

@cguardia cguardia commented Jun 25, 2019

This required a good deal of research. I tried to document why we are not implementing some stuff from what's left in the TODO document. Please take a look to see if I'm wrong on something.

@googlebot googlebot added the cla: yes This human has signed the Contributor License Agreement. label Jun 25, 2019
@cguardia cguardia requested a review from chrisrossi June 25, 2019 08:27
available. It still uses the same signature, but does not support original
Configuration methods.

Similarly,b ecause ``google.appengine.datastore.datastore_query.Order`` is no
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: s/Similarly,b ecause/Similarly, because/

====

There are some methods from the ``key`` module that are not implemented in
this version of `ndb`:
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we want to explain why?

Choose a reason for hiding this comment

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

I agree. Based on https://cloud.google.com/appengine/docs/standard/python/ndb/keyclass#class_methods, I think this could say:
These methods were used to pass keys to and from the db Datastore API, which is no longer supported.

- The `BlobProperty` constructor only sets `_compressed` if explicitly
passed. The original set `_compressed` always.
- In the exact same fashion the `JsonProperty` constructor only sets
`_json_type` if explicitly passed.]

Choose a reason for hiding this comment

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

] seems to be a typo.


client = ndb.Client()

with context as client.context():
Copy link
Contributor

Choose a reason for hiding this comment

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

swap context and client.context()


Aside from this, there are many differences between the Datastore APIs
provided by GAE and those provided by the newer Google Cloud Platform. These
diffeences have required some code and API changes as well.
Copy link
Contributor

Choose a reason for hiding this comment

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

typo: diffeences

- ReducedFuture.
- SerialQueueFuture.
- set_context.
- toplevel.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think we can still implement toplevel. Or did you look at it and find out we couldn't?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I only took a quick glance while going through the TODO list, and I thought its reliance on _make_cloud_datastore_context meant it was out. I didn't stop to think about the implementation. Do you think I should remove it from this list?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's doable. Let's keep this on our TODO list, still.

made obsolete by new Python 3 features, while others have been discarded due
to implementation differences in the new `ndb`.

Possibly the most used utility from this module outside of `ndb` code, is the
Copy link
Contributor

Choose a reason for hiding this comment

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

Until we go back and add py27 compatibility, at least.

because that's the namespace passed in when setting up the client.

Django Middleware
=================
Copy link
Contributor

@chrisrossi chrisrossi Jun 26, 2019

Choose a reason for hiding this comment

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

So, a couple things here:

  1. A context is thread local. Recommended practice is one context per request. So you probably want to create the client in __init__ but create the context in __call__.

  2. __call__ looks like a great place to use a with statement.

Maybe something more like:

    from google.cloud import ndb

    class NDBMiddleware(object):
        def __init__(self, get_response):
            self.get_response = get_response
            self.client = ndb.Client()

        def __call__(self, request):
            context = self.client.context()
            request.ndb_context = context
            with context:
                response = self.get_response(request)
            return response

Choose a reason for hiding this comment

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

If it is any help, putting this in my Django middleware, I am receiving AttributeError: '_GeneratorContextManager' object has no attribute 'use'. Seems to be working without the use but I don't have enough "context" to know if that will break something else.

Putting the context in the __init__ definitely broke things for the second request that uses ndb.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks a lot, I'm going to test this more and make it work before the merge.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, I forgot that Client.context calls Context.use for you. I will correct my snippet.

docs/migrating.rst Show resolved Hide resolved
shims for most of them, which can be imported from the `ndb.exceptions`
package, like this::

from ndb.exceptioms import BadRequestError, BadArgumentError

Choose a reason for hiding this comment

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

typo: exceptioms

Copy link

@darrencarlton darrencarlton left a comment

Choose a reason for hiding this comment

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

Hi Carlos:
I'm new to this project, so hopefully my suggestions make sense.

implementation, and sometimes even to remove exisitng functionality
altogether.

Because one of the main objectives of this rewrite was to be able to use `ndb`

Choose a reason for hiding this comment

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

I initially assumed "independently from GAE" meant "in another Google Cloud Product". How about:
One of the main objectives of this rewrite was to enable ndb for use in any Python environment, not just Google App Engine. As a result, many of the ndb APIs that relied on GAE environment and runtime variables, resources, and legacy APIs have been dropped.

====

There are some methods from the ``key`` module that are not implemented in
this version of `ndb`:

Choose a reason for hiding this comment

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

I agree. Based on https://cloud.google.com/appengine/docs/standard/python/ndb/keyclass#class_methods, I think this could say:
These methods were used to pass keys to and from the db Datastore API, which is no longer supported.

implementation, and sometimes even to remove exisitng functionality
altogether.

Because one of the main objectives of this rewrite was to be able to use `ndb`

Choose a reason for hiding this comment

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

I assumed "use ndb independently from Google App Engine" meant "use nbd in another Google Cloud product." How about changing the paragraph to this:
One of the main objectives of this rewrite was to enable ndb for use in any Python environment, not just Google App Engine. As a result, ndb APIs that depended on GAE environment and runtime variables, resources, or legacy APIs have been dropped.

- Similarly, the `DateTimeProperty` constructor only sets `_auto_now` and
`_auto_now_add` if explicitly passed.
- `TextProperty(indexed=True)` and `StringProperty(indexed=False)` are no
longer supported.

Choose a reason for hiding this comment

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

Does this mean that TextProperty can no longer be indexed, whereas StringProperty is always indexed?
If so, for clarification can you add:
That is, TextProperty can no longer be indexed, whereas StringProperty is always indexed.

significantly from the public API used by App Engine to the current published
API. Additionally, this version of NDB mostly delegates to
`google.cloud.datastore` for parsing data returned by RPCs, which is a
significant internal refactoring.

Choose a reason for hiding this comment

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

I'm a little confused here. Are you saying that the old NDB library included some undocumented APIs that dealt directly with protocol buffers? Also, from reading the MIGRATION_NOTES, I'm not sure it would be possible for someone to tell which APIs dealt with protobufs.

How about this:
The old NDB library included some undocumented APIs that dealt directly with Datastore protocol buffers. These APIs will no longer work. Rewrite any code that used the following classes, properties, or methods:

  • ModelAdapter
  • Property._db_get_value, Property._db_set_value
  • Property._db_set_compressed_meaning and Property._db_set_uncompressed_meaning
  • Model._deserialize and Model._serialize
  • model.make_connection

@cguardia
Copy link
Contributor Author

cguardia commented Jul 2, 2019

@chrisrossi I think this is ready for another pass.

@yoshi-automation yoshi-automation added the 🚨 This issue needs some love. label Jul 2, 2019
@cguardia
Copy link
Contributor Author

cguardia commented Jul 2, 2019

@darrencarlton @lolsheeplol @BenWhitehead @chrisrossi @sadovnychyi @plumSemPy Thanks for all your input and suggestions. We are looking into how/where to best incorporate this documentation into the project.

Copy link
Contributor

@chrisrossi chrisrossi 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 pending minor tweaks.

- Key.from_old_key.
- Key.to_old_key.

These methods were used to pass keys to and from the db Datastore API, which is
Copy link
Contributor

Choose a reason for hiding this comment

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

Should make obvious that db is a name of an old product. In this case, the predecessor to ndb.

- ReducedFuture.
- SerialQueueFuture.
- set_context.
- toplevel.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it's doable. Let's keep this on our TODO list, still.

- Model._deserialize and Model._serialize.
- model.make_connection.

will no longer work. The Datastore `.protobuf` definitions have changed
Copy link
Contributor

Choose a reason for hiding this comment

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

This needs to be reworked or elided following the edit above.

@yoshi-automation yoshi-automation removed 🚨 This issue needs some love. 🚨 labels Jul 3, 2019
@cguardia cguardia added the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jul 6, 2019
@yoshi-kokoro yoshi-kokoro removed the kokoro:force-run Add this label to force Kokoro to re-run the tests. label Jul 6, 2019
Copy link
Contributor

@andrewsg andrewsg left a comment

Choose a reason for hiding this comment

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

Thank you for your work on this.

we can no longer assume it's running in the context of a GAE request.

The `ndb` client uses ``google.auth`` for authentication, which is how APIs in
Google Cloud Platform work. The client can take a `credentials` parameter or
Copy link
Contributor

Choose a reason for hiding this comment

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

Recommend "The ndb client uses google.auth for authentication, consistent with other Google Cloud Platform client libraries."

The `ndb` client uses ``google.auth`` for authentication, which is how APIs in
Google Cloud Platform work. The client can take a `credentials` parameter or
get the credentials using the `GOOGLE_APPLCATION_CREDENTIALS` environment
variable, which is the recommended option.
Copy link
Contributor

Choose a reason for hiding this comment

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

Recommend we also link to https://cloud.google.com/storage/docs/reference/libraries for authentication advice.

The context is not thread safe, so for threaded applications, you need to
generate one context per thread. This is particularly important for web
applications, where the best practice would be to generate a context per
request.
Copy link
Contributor

Choose a reason for hiding this comment

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

This is confusing. If you have a web application, where the best practice would be to generate one context per request, and you need multiple threads inside that request, what should you do?

If the answer is "generate multiple contexts" then maybe something like this?

"In a web application, a typical best practice is to generate one context per request. However, a context object only applies to a single thread; in the case that multiple threads are used for a single request, a new context should be generated for every thread that will use the NDB library."

@cguardia cguardia merged commit 0b7eeed into googleapis:master Jul 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes This human has signed the Contributor License Agreement.
Projects
None yet
Development

Successfully merging this pull request may close these issues.