Jump to: navigation, search

Difference between revisions of "Trove/extensionsrefactor"

(Cons:)
m
 
(10 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== Dynamic route proposal: ==
+
= Dynamic route proposal =
=== Changes: ===
+
== Changes ==
 
*Remove existing extensions and move routes mapped into base API app. Ex: instances/<instance_id>/users
 
*Remove existing extensions and move routes mapped into base API app. Ex: instances/<instance_id>/users
 
*Add code to inspect instance_id and map it to an instance type.. Redis Postgres MySQL etc.
 
*Add code to inspect instance_id and map it to an instance type.. Redis Postgres MySQL etc.
 
*Have "proxy" route dynamically load a service for each database type either with importlib or stevedore whatever.
 
*Have "proxy" route dynamically load a service for each database type either with importlib or stevedore whatever.
*Have the route dynamically accept requests for special edge cases for differing database engines. Ex: Default database for postgres on user create while MySQL does not use one.
+
*Have the route dynamically accept requests for special edge cases for differing database engines.
=== Why do it this way? ===
+
**Ex: Default database required for postgres on user create while MySQL does not use one.
*Does not change existing API spec. No need to version the API.
+
== Why do it this way? ==
*Less cruft in API vs having prefix based user or backup requests. Ex /instances/<instance_id>/mysql/users.
+
*Does not change existing API URL spec. No need to version API.
*Generate plugins more quickly and never have routing collisions for new database types. As the request body expected is based off of database type not route.
+
*Fewer routes in API vs having prefix/namespace based approach for commonly supported requests like users or backup.  
*Allows for multiple versions or forks of different Database engines more easily. Ex: Allow multiple versions of a Database engine that have differing user create requirements.. (Can't think of an explicit so maybe this is a bad example.)
+
**Ex /instances/<instance_id>/mysql/users.
*Allows the interface for users who only want to support one DB engine to be simplified. Ex: No database type specific URI prefix.
+
**Ex /instances/<instance_id>/postgres/users.
*Allows the base URI mappings to be the same for all databases that have a common type. Ex: users, backups etc.
+
**Ex /instances/<instance_id>/mongodb/users.
*Probably less code overall depending on how the prefix specific routes could be added.
+
*Allows for multiple versions or forks of different Database engines more easily.  
*I like this one more =P.
+
**Ex: Allow multiple versions of a Database engine that have differing user create requirements.. (Can't think of anything that exactly matches that scenario so maybe this is a bad example. However, it does allow for differing versions of one database application.)
=== Cons: ===
+
**This could be true of the namespaced option as well
 +
*Allows the interface for users who only want to support one DB engine to be simplified.  
 +
**Ex: No database type specific URI prefix.
 +
*Allows the base URI mappings to be the same for all databases that have a common type.  
 +
**Ex: users, backups etc.
 +
*More like the nova API.
 +
*Conrad likes this one more =P.
 +
 
 +
== Cons ==
 
*Less explicit then using database specific prefixes.
 
*Less explicit then using database specific prefixes.
== Alternative Solutions: ==
+
*Post body may vary significantly based on database type
== Use a db specific routing methodology: ==
+
*Harder to create a schema for.
=== Changes: ===
+
*More difficult to write JsonSchema stuff for.
*Remove existing extensions and move routes mapped into base API app. Ex instances/<instance_id>/<db_type>/users
+
*Harder to document without referring to various database types within most entries.
 +
*If you think about writing the client, it would probably lead to the creation of an even larger "God object" for Instance.
 +
 
 +
= Alternative Solutions =
 +
== Use a db-specific/namespaced routing methodology ==
 +
=== Changes ===
 +
*Remove or deprecate existing extensions and move routes mapped into base API app. Ex instances/<instance_id>/<db_type>/users
 +
Alternate example: <db_type>/instances/<instance_id>/users for users of a specific db_type, instances/<instance_id>/action for an action that could apply to any instance.
 
*Add code to inspect instance_id and verify it's instance type.. Redis Postgres MySQL etc.
 
*Add code to inspect instance_id and verify it's instance type.. Redis Postgres MySQL etc.
 
*Have "proxy" route dynamically load a service for each database type either with importlib or stevedore whatever.
 
*Have "proxy" route dynamically load a service for each database type either with importlib or stevedore whatever.
Line 26: Line 41:
 
*More explicit than dynamic type mapping.
 
*More explicit than dynamic type mapping.
 
*Might be easier to write docs as each URI is explicit rather than implicit based off of its type.
 
*Might be easier to write docs as each URI is explicit rather than implicit based off of its type.
*Contract is explicit for each URI rather than explicit for database type.
+
*Contract is explicit for each URI rather than variable based on database type.
 +
*Databases with similar functionality could use polymorphism to override or extend functionality of the routing modules
 
*hub_cap is all about this one!
 
*hub_cap is all about this one!
=== Cons: ===
+
*Kenneth is currently on this side of the fence
*Potential api version change.
+
=== Cons ===
*Wonky for Users only using one DB type and the solution to that edge case is implement a default type for instances/<instance_id> and that is the same as supporting dynamic type resolution.
+
*Potential api version change. (If existing extentions and routes are removed)
*Lots of routes to mange depending on how we decide to implement the routing.
+
*Could be wonky for users only using one DB type.
 +
**A solution for that edge case may be to implement aliasing for instances/<instance_id>/<action> and that is the same as supporting dynamic type resolution essentially.
 +
*Lots of routes to manage depending on how we decide to implement the routing.
 +
**These could be handled by routing modules for each database type
 
*Need to know what type db is in order to know what uri to post to.
 
*Need to know what type db is in order to know what uri to post to.
  
== Client Examples: ==
+
= Client Examples =
=== Client interaction flow with dynamic type resolution for user add example ===
+
== Client interaction flow with dynamic type resolution for user add example ==
 
*Determine type from instances listing.
 
*Determine type from instances listing.
 
*post to instances/<instance_id>/users with db specific body.
 
*post to instances/<instance_id>/users with db specific body.
Line 41: Line 60:
 
*404 if db does not have concept of users.
 
*404 if db does not have concept of users.
 
*2** if all is well
 
*2** if all is well
=== Client interaction flow with static db routes for use add example ===
+
== Client interaction flow with namespaced routes for user add example ==
 
*Determine type from instance listing.
 
*Determine type from instance listing.
 
*post to instances/<instance_id>/<db_type>/users with db specific body.
 
*post to instances/<instance_id>/<db_type>/users with db specific body.
 
*validate input.
 
*validate input.
*404 if db does not have concept of users.
+
*404 if db does not have concept of users. (Comment: if the db type was explicit in the request, why would this ever happen? It would be very clear from the docs that the path was invalid and the Python client bindings, as well as other bindings, would not allow it.)
 
*2** if all is well.
 
*2** if all is well.

Latest revision as of 20:18, 24 July 2013

Dynamic route proposal

Changes

  • Remove existing extensions and move routes mapped into base API app. Ex: instances/<instance_id>/users
  • Add code to inspect instance_id and map it to an instance type.. Redis Postgres MySQL etc.
  • Have "proxy" route dynamically load a service for each database type either with importlib or stevedore whatever.
  • Have the route dynamically accept requests for special edge cases for differing database engines.
    • Ex: Default database required for postgres on user create while MySQL does not use one.

Why do it this way?

  • Does not change existing API URL spec. No need to version API.
  • Fewer routes in API vs having prefix/namespace based approach for commonly supported requests like users or backup.
    • Ex /instances/<instance_id>/mysql/users.
    • Ex /instances/<instance_id>/postgres/users.
    • Ex /instances/<instance_id>/mongodb/users.
  • Allows for multiple versions or forks of different Database engines more easily.
    • Ex: Allow multiple versions of a Database engine that have differing user create requirements.. (Can't think of anything that exactly matches that scenario so maybe this is a bad example. However, it does allow for differing versions of one database application.)
    • This could be true of the namespaced option as well
  • Allows the interface for users who only want to support one DB engine to be simplified.
    • Ex: No database type specific URI prefix.
  • Allows the base URI mappings to be the same for all databases that have a common type.
    • Ex: users, backups etc.
  • More like the nova API.
  • Conrad likes this one more =P.

Cons

  • Less explicit then using database specific prefixes.
  • Post body may vary significantly based on database type
  • Harder to create a schema for.
  • More difficult to write JsonSchema stuff for.
  • Harder to document without referring to various database types within most entries.
  • If you think about writing the client, it would probably lead to the creation of an even larger "God object" for Instance.

Alternative Solutions

Use a db-specific/namespaced routing methodology

Changes

  • Remove or deprecate existing extensions and move routes mapped into base API app. Ex instances/<instance_id>/<db_type>/users
Alternate example: <db_type>/instances/<instance_id>/users for users of a specific db_type, instances/<instance_id>/action for an action that could apply to any instance. 
  • Add code to inspect instance_id and verify it's instance type.. Redis Postgres MySQL etc.
  • Have "proxy" route dynamically load a service for each database type either with importlib or stevedore whatever.
  • Have the route accept requests for differing database engines. Ex. Default database for postgres on user create while MySQL does not use one.

Why do it this way?

  • More explicit than dynamic type mapping.
  • Might be easier to write docs as each URI is explicit rather than implicit based off of its type.
  • Contract is explicit for each URI rather than variable based on database type.
  • Databases with similar functionality could use polymorphism to override or extend functionality of the routing modules
  • hub_cap is all about this one!
  • Kenneth is currently on this side of the fence

Cons

  • Potential api version change. (If existing extentions and routes are removed)
  • Could be wonky for users only using one DB type.
    • A solution for that edge case may be to implement aliasing for instances/<instance_id>/<action> and that is the same as supporting dynamic type resolution essentially.
  • Lots of routes to manage depending on how we decide to implement the routing.
    • These could be handled by routing modules for each database type
  • Need to know what type db is in order to know what uri to post to.

Client Examples

Client interaction flow with dynamic type resolution for user add example

  • Determine type from instances listing.
  • post to instances/<instance_id>/users with db specific body.
  • validate input.
  • 404 if db does not have concept of users.
  • 2** if all is well

Client interaction flow with namespaced routes for user add example

  • Determine type from instance listing.
  • post to instances/<instance_id>/<db_type>/users with db specific body.
  • validate input.
  • 404 if db does not have concept of users. (Comment: if the db type was explicit in the request, why would this ever happen? It would be very clear from the docs that the path was invalid and the Python client bindings, as well as other bindings, would not allow it.)
  • 2** if all is well.