-
Notifications
You must be signed in to change notification settings - Fork 344
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
[Issue 1907] TO API for backup edge cachegroup #2029
Conversation
Can one of the admins verify this patch? |
1 similar comment
Can one of the admins verify this patch? |
@Vijay-1 can you change the title of this PR so it's more descriptive of the actual change? A link in the title doesn't work well.. Something like this is good: |
CHANGELOG.md
Outdated
@@ -34,6 +34,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). | |||
- /api/1.3/system/info | |||
- /api/1.3/types (R) | |||
- Fair Queuing Pacing: Using the FQ Pacing Rate parameter in Delivery Services allows operators to limit the rate of individual sessions to the edge cache. This feature requires a Trafficserver RPM containing the fq_pacing experimental plugin AND setting 'fq' as the default Linux qdisc in sysctl. | |||
- Backup Edge Cache group: Backup Edge group for a particular cache group can be configured using Traffic Router's cr-config.json configuration file. With this, users will be able control traffic within portions of their network, thereby avoiding choosing fallback cache groups using geo coordinates(getClosestAvailableCachegroup). This can be controlled using "backupLocations" which contains configuration for backup cache groups parsed from the cr-config.json which gets populated using the APIs detailed [here](http://traffic-control-cdn.readthedocs.io/en/latest/development/traffic_ops_api/v12/cachegroup_fallbacks.html) |
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.
Since the changelog is user visible, its better to describe the changes as configured using Traffic Ops API. You could also make the description more concise as you have more detailed documentation elsewhere.
Consider something along the lines of:
Configure a backup list of edge cache groups through the Traffic Ops API. A Backup edge cache group is used if the matched group in the CZF is not available. If the backup edge cache groups are not available, geo location can optionally be used as a further backup. See APIs here...
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.
Will do.
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.
Seems to be some copy/paste errors and I think the API response structure needs to be rethought. Also, make sure you read our API guidelines for some ideas on the response structure.
"text": "Backup configuration for 51 successful." | ||
} | ||
], | ||
"response": { |
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.
this data structure doesn't follow the pattern currently represented in the rest of the API. Instead it should look more like this:
response: [ { "order": -1, "name" :"GROUP2" }, { "order": 1, "name" :"GROUP3" } ]
there is no need for GROUP1->fallbacks->list
it is implied from the structure of the route (GET /api/1.2/cachegroups/:id/fallbacks) that a list (array) is being returned.
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.
+1, the extra keys will make client code unnecessarily complex.
|
||
**POST /api/1.2/cachegroups/:id/fallbacks** | ||
|
||
Create cache group. |
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're not creating a cache group. can you add a description of what this route is used for?
**Request Example** :: | ||
|
||
{ | ||
"fallbacks": |
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.
I don't think there is any need for the fallbacks key.
"text":"Backup configuration for 51 successful." | ||
} | ||
], | ||
"response":{ |
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.
again, this should just be an array of "fallbacks"
|
||
| | ||
|
||
**PUT /api/1.2/cachegroups/:id/fallbacks** |
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.
How is PUT different than POST?
POST should be for creating fallbacks for a cachegroup
PUT should be for updating a specific fallback so the route should be PUT /api/1.2/cachegroups/:id/fallbacks/:fb_id
|
||
# -- CACHEGROUP-Fallbacks: CRUD | ||
$r->get("/api/$version/cachegroups/:id/fallbacks" => [ id => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'CachegroupFallback#show', namespace => $namespace ); | ||
$r->post("/api/$version/cachegroups/:id/fallbacks" => [ id => qr/\d+/ ] )->over( authenticated => 1, not_ldap => 1 )->to( 'CachegroupFallback#create', namespace => $namespace ); |
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.
what happens if i do 2 POSTs in a row. does the 2nd POST wipe out the fallbacks of the first or does it add to it?
what is the intent of PUT? does a PUT wipe out all the fallbacks and replace them?
/api/1.2/cachegroups/fallbacks | ||
++++++++++++++++++++++++++++++ | ||
|
||
**GET /api/1.2/cachegroups/:id/fallbacks** |
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 description of what this route is for?
|
||
**PUT /api/1.2/cachegroups/:id/fallbacks** | ||
|
||
Create cache group. |
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 description of what this route is used for. It is not clear to me what a PUT does. Does it replace all existing fallbacks?
|
||
**DELETE /api/1.2/cachegroups/{:id}/fallbacks** | ||
|
||
Delete cache group. The request to delete a cache group, which has servers or child cache group, will be rejected. |
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.
Need a real description here.
@@ -57,6 +57,7 @@ sub index { | |||
"lastUpdated" => $row->last_updated, | |||
"parentCachegroupId" => $row->parent_cachegroup_id, | |||
"parentCachegroupName" => ( defined $row->parent_cachegroup_id ) ? $idnames{ $row->parent_cachegroup_id } : undef, | |||
"fallback_to_closest" => \$row->fallback_to_closest, |
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.
API responses need to be camelcase
@mitchell852 I have a comment on one of your comments:
In this we dont have a specific fallback (i.e) no unique id associated with fallback. This configuration is always tied with a cache group id and hence cache group id alone is enough. |
@Vijay-1 - can you just do 3 endpoints? I still dont' understand the need for the PUT. GET /api/cachegroups/:id/fallbacks <-- return an array of fallbacks for the cachegroup |
|
||
**PUT /api/1.2/cachegroups/:id/fallbacks** | ||
|
||
Updates an already existing fallback list for the cache group (Existing fallback list will be deleted). |
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 don't you delete this route and just use POST instead where POST always creates fallbacks and removes the current ones if there are any. PUTs are used for "updates" and you are not updating a resource here. Instead, you are deleting and creating so the POST makes more sense.
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.
This has be discussed earlier and here is the summary of how it was thought about to start :
1. POST: receive a full list of ordered backups and create the fallback list. If the fallback list already exists, render a failure.-
PUT: receive a full list of ordered backups, delete the existing
fallback list, and create a new fallback list. If the fallback list
does not exist yet, render a failure. -
DELETE: delete the existing fallback list for a cachegroup. If the
fallback list does not exist, render a failure. -
GET: return the existing fallback list for a cachegroup. If the
fallback list does not exist, render a failure.
So essentially POST creates a resource., PUT can update (replace / update) a resource which is already POST-ed. PUT can only operate on an already POST-ed resource. Does that make sense.
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.
May be i should reword that sentence like the following:
Updates / replaces an already existing fallback list for the cache group.
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.
yes, it makes sense but i don't really understand why you'd want 4 endpoints with extra logic in the POST and PUT endpoints (if exists, fail or if not exists, fail).
Instead if you just make the POST do a delete all/create (which is really a replace), then it can be used in both scenarios. then there becomes no confusion about the difference between POST and PUT
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.
Ok. Makes sense. I agree that we can do away with PUT. Hope every one is fine with this.
After looking over how this endpoint can be written and go, and our plan for api design moving forward (https://cwiki.apache.org/confluence/display/TC/API+Guidelines) I would suggest a few changes: Change the route to not be nested. We are moving away from nested routes to remove ambiguity related to keys and simplify routing concerns. Change the api response to include the cachegroup id in each fallback object in the array. This allows for more options for filtering and more accurately represents the data in the database. Change the name key to something more descriptive / tied to the fallback cachegroup to make it clear. With these changes the GET request would change from:
to:
These changes will allow the api to easily use some prebuilt components and will give us some additional functionality for free in go, such as being able to filter by the fallback group's name and get all the cachegroups that fall back to it for example. |
In perl/ Mojo, i can see this query params only for indexes, where we are fetching an entire set and ordering , say for example all available cache groups/ delivery services etc and ordering them by id / name etc. Say for example: GET response may be a list of cache groups which has server 5 as backup whereas /cachegroup_fallbacks?cacheGroupId=5 is that what you meant? I dont think current Perl/ Mojo implementation has any thing of this sort. AFIK, the only point i see in supporting these APIs is the similarity it may share with GO APIs. Is this alone is enough to change nested routes to the ones which supports query params? Why cant we leave this as such for Perl / Mojo? |
@DylanVolz - i am not convinced that moving the URL to top level (as cachegroup_fallbacks) for this functionality is the right direction. I think the guideline wiki cited a good use of toplevel for profile & parameters. In such case, the parameters and profiles are loosely associated where params don't necessarily get associated with any profile. The fallbacks however are different in that it's just some additional, optional attributes to an otherwise regular cachgroup therefore should be accessible only through ../cachgroup/... hierarchy ihmo. I don't think the database storage normalization has to necessarily influence the API representation. |
@hongfeiweb - we're trying to move away from "route" or "path" parameters to remove some of the ambiguity that they have caused. Also, to condense our number of routes. For example, we have routes like this: GET /api/servers/{id} We'd rather just have one route that supports multiple query params. GET /api/servers?id=4 or GET /api/servers?hostname=foo-bar It's not that I'm opposed to nested routes per se, but it's hard to have nested routes if you eliminate route/path parameters. I've updated the TO API guidelines to reflect our new approach to APIs as we move forward with Golang: https://cwiki.apache.org/confluence/display/TC/API+Guidelines |
@DylanVolz |
@mitchell852 I think this looks good now, I verified it works as expected. The only outstanding issue is the merging of #2080 that @rawlinp pointed out. Until that is updated this feature won't be able to be used, but I am unsure that blocks this PR necessarily. |
@rawlinp - can you look at the changes made to TR? |
|
||
**Request Example** :: | ||
|
||
[ |
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.
To be consistent with the other routes, I would have expected the request to look like:
[ { "cacheGroupId": 1, "fallbackId": 27, "fallbackOrder": 10 }] instead of using fallbackName
and what does this do exactly? Create the row in the cachegroup_fallbacks table if it doesn't exist? and update the row if it does exist?
|
||
| | ||
|
||
**DELETE /api/1.2/cachegroup_fallbacks** |
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 can't delete just one fallback? you can only delete all of them for a cachegroup?
seems like you should be able to do both (delete one fallback or ALL fallbacks for a cg)
DELETE /api/1.2/cachegroup_fallbacks?id=45
DELETE /api/1.2/cachegroup_fallbacks?cacheGroupId=3
@@ -164,6 +166,7 @@ sub update { | |||
latitude => $params->{latitude}, | |||
longitude => $params->{longitude}, | |||
parent_cachegroup_id => $params->{parentCachegroupId}, | |||
fallback_to_closest => $params->{fallbackToClosest}, |
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.
Because this field was not added to Traffic Portal, users of the TP will always be setting this to null when they update a cache group. Is that OK?
I think you need to add this field to the Traffic Portal - form.cacheGroup.tpl.html
@Vijay-1 - I think you need to rethink your design of this feature. The way you have it built will be very difficult to incorporate into the Traffic Portal which uses POSTs for create only and PUTs for update. Here are my suggestions: GET /cachegroup_fallbacks[?id=|?cachegroupId=|?fallbackId=]
POST /cachegroup_fallbacks [ { "cacheGroupId": 1, "fallbackId": 27, "fallbackOrder": 10 }, {...} ]
PUT /cachegroup_fallbacks[?id=] { "cacheGroupId": 1, "fallbackId": 27, "fallbackOrder": 42 }
DELETE /cachegroup_fallbacks[?id=|?cachegroupId=]
|
@mitchell852 Given below is the original proposal:
Also i am not sure why we need Get all cachegroup fallbacks. I dont see any point in pulling all the cachegroup fallbacks instead it makes sense that we always retrieve fallbacks with respect to a cache group. Also I am not sure on why we need to delete a specific fallback if there is an update (PUT) available |
@mitchell852 It should be either cacheGroupId or fallbackId. Both Ids are actually cache group Ids(cachegroup Table). Since cachegroup_fallbacks is always dependent on cachegroup only we can have the following GET API endpoints. |
The Traffic Portal typically works like this. Here are a few scenarios:
or
or
so basically if you want to integrate your apis into the TP, you need endpoints to do the following:
without these routes, you are going to have a hard time integrating these apis into the traffic portal. actually, you could probably do without #2 and #3 and just go with:
|
Some minot modification from your suggestions. Request your views before actually modifying those. delete one create one
Most of this functionalities is already there except for POST's deletion and Delete's specific row requirement. |
@Vijay-1 - i think that makes sense fetch list Fallbacks for a cacheGroupId ^^ although the cg is not needed in the response, it keeps the structure the same regardless of which query param you send in (fallbackId or cacheGroupId). delete one but for POST (create), why not just one route like this: POST /api/{version}/cachegroup_fallbacks where the json request is an array of one or more that looks like this: [ { cachegroupId: 3, fallbackId: 6 }, { cachegroupId: 3, fallbackId: 7 }, { cachegroupId: 3, fallbackId: 8 } ] ^^ insert a row for each item in the array. if it is already in the database table, skip it. |
@mitchell852
GET Response Also POST , updates rather than skipping , because there may be a change in Order |
this seems ok from an api perspective. need someone to review/test the TR part. @rawlinp @rivasj @elsloo @ajschmidt any takers? |
@@ -250,6 +250,15 @@ sub gen_crconfig_json { | |||
if ( $row->type->name =~ m/^EDGE/ ) { | |||
$data_obj->{'edgeLocations'}->{ $row->cachegroup->name }->{'latitude'} = $row->cachegroup->latitude + 0; | |||
$data_obj->{'edgeLocations'}->{ $row->cachegroup->name }->{'longitude'} = $row->cachegroup->longitude + 0; | |||
$data_obj->{'edgeLocations'}->{ $row->cachegroup->name }->{'backupLocations'}->{'fallbackToClosest'} = $row->cachegroup->fallback_to_closest ? "true" : "false"; | |||
|
|||
my $rs_backups = $self->db->resultset('CachegroupFallback')->search({ primary_cg => $row->cachegroup->id}, {order_by => 'set_order'}); |
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.
gen_crconfig_json was rewritten in Golang so this logic will need to be added there as well otherwise it will be lost. You might want to reach out to @rob05c
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.
@Vijay-1 - this can't be merged until this is addressed.
@@ -0,0 +1,38 @@ | |||
/* | |||
|
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.
this migration won't work. the date is too old.
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.
Renamed.
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.
TR changes still seem good, but I have some suggestions on the TO side
@@ -367,264 +367,3 @@ Traffic Ops accesses each extension through the addition of a URL route as a cus | |||
Development Configuration | |||
-------------------------- | |||
To incorporate any custom Extensions during development set your PERL5LIB with any number of directories with the understanding that the PERL5LIB search order will come into play, so keep in mind that top-down is how your code will be located. Once Perl locates your custom route or Perl package/class it 'pins' on that class or Mojo Route and doesn't look any further, which allows for the developer to *override* Traffic Ops functionality. | |||
|
|||
API |
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.
Did you mean to remove this section? Seems totally unrelated to this change and maybe pulled in accidentally when rebasing
@@ -57,6 +57,7 @@ sub index { | |||
"lastUpdated" => $row->last_updated, | |||
"parentCachegroupId" => $row->parent_cachegroup_id, | |||
"parentCachegroupName" => ( defined $row->parent_cachegroup_id ) ? $idnames{ $row->parent_cachegroup_id } : undef, | |||
"fallbackToClosest" => \$row->fallback_to_closest, |
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.
I saw API reference documentation for the new cachegroup_fallbacks
endpoint, but the existing cachegroup API reference documentation should also be updated to show this new fallbackToClosest
field.
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.
Addressed.
|
||
-- cachegroup_fallbacks | ||
CREATE TABLE cachegroup_fallbacks ( | ||
primary_cg bigint, |
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 primary_cg
and backup_cg
both be NOT NULL
as well? I'm not sure null values would make sense there.
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.
There wont be any Database OP with these values as Null. Do we really need to do this?
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.
If there's no DB op with these values as null, then that's all the more reason to do it. Generally we should always be using NOT NULL
wherever it makes sense. That way if somebody changes the API implementation, they can't accidentally make it so that it accepts null values.
UNIQUE (primary_cg, set_order) | ||
); | ||
|
||
ALTER TABLE cachegroup ADD COLUMN fallback_to_closest BOOLEAN DEFAULT TRUE; |
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.
This should also probably be NOT NULL? Might save us from a bunch of unnecessary null checks when reading from the DB.
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.
NOT NULL may fail any DB Ops if the User doesnt supply fallback_to_closest. Also, this is not a mandatory field by design and hence i think we dont have to change this.
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.
Currently it looks like your perl API implementation protects against clients not supplying fallbackToClosest
by just inserting the value true
in that case. However, since the cachegroup API is now written in and handled by the golang API, it will never insert a value there and will always default to true
. Eventually we'll need to implement it there too so that we can actually set it to false
when needed. I think columns that have a default could always be made to be NOT NULL
by having the API insert the default when null, but generally I don't feel too strongly about it.
$cache_id = $param_array[0]{cacheGroupId}; | ||
} | ||
|
||
if ( !defined($params) ) { |
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.
seems like this check should be above the previous one
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.
Yes. Will address.
} | ||
|
||
#only integers | ||
if ( $cache_id !~ /^\d+?$/ ) { |
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.
All the validation code should probably reside in its own function like is_valid_cachegroup_fallback
that checks the request format, required fields, types, etc. and returns helpful error messages for invalid requests. It should be used here and reused in update
. Right now $config->{something}
could be undefined and would probably give the message "No such Cachegroup id undefined" which isn't very clear. Plus it'll make it easier to write the validation code when porting it to Go.
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 have to make sure the logic that you added to topology.pm is added to golang
@@ -250,6 +250,15 @@ sub gen_crconfig_json { | |||
if ( $row->type->name =~ m/^EDGE/ ) { | |||
$data_obj->{'edgeLocations'}->{ $row->cachegroup->name }->{'latitude'} = $row->cachegroup->latitude + 0; | |||
$data_obj->{'edgeLocations'}->{ $row->cachegroup->name }->{'longitude'} = $row->cachegroup->longitude + 0; | |||
$data_obj->{'edgeLocations'}->{ $row->cachegroup->name }->{'backupLocations'}->{'fallbackToClosest'} = $row->cachegroup->fallback_to_closest ? "true" : "false"; | |||
|
|||
my $rs_backups = $self->db->resultset('CachegroupFallback')->search({ primary_cg => $row->cachegroup->id}, {order_by => 'set_order'}); |
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.
@Vijay-1 - this can't be merged until this is addressed.
@mitchell852 @rawlinp |
lib/go-tc/cachegroupfallback.go
Outdated
// A List of CACHEGROUPFALLBACKs Response | ||
// swagger:response CACHEGROUPFALLBACKsResponse | ||
// in: body | ||
type CACHEGROUPFALLBACKsResponse struct { |
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.
camelcase should be used to keep in style with the rest of the go code: CachegroupFallbacksResponse
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.
Ok. Will change this.
|
||
-- cachegroup_fallbacks | ||
CREATE TABLE cachegroup_fallbacks ( | ||
primary_cg bigint, |
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.
If there's no DB op with these values as null, then that's all the more reason to do it. Generally we should always be using NOT NULL
wherever it makes sense. That way if somebody changes the API implementation, they can't accidentally make it so that it accepts null values.
UNIQUE (primary_cg, set_order) | ||
); | ||
|
||
ALTER TABLE cachegroup ADD COLUMN fallback_to_closest BOOLEAN DEFAULT TRUE; |
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.
Currently it looks like your perl API implementation protects against clients not supplying fallbackToClosest
by just inserting the value true
in that case. However, since the cachegroup API is now written in and handled by the golang API, it will never insert a value there and will always default to true
. Eventually we'll need to implement it there too so that we can actually set it to false
when needed. I think columns that have a default could always be made to be NOT NULL
by having the API insert the default when null, but generally I don't feel too strongly about it.
#only integers | ||
if ( $id !~ /^\d+?$/ ) { | ||
&log( $self, "No such Cachegroup id $id"); | ||
return $self->success([]); |
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.
shouldn't this return a 500 alert not a success?
my $cachegroup = $self->db->resultset('Cachegroup')->search( { id => $id } )->single(); | ||
if ( !defined($cachegroup) ) { | ||
&log( $self, "No such Cachegroup $id"); | ||
return $self->success([]); |
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.
404 not found?
|
||
my $rs_data = $self->db->resultset('CachegroupFallback')->create($values)->insert(); | ||
if ( !defined($rs_data)) { | ||
&log( $self, "Database operation for backup configuration for cache group $cache_id failed."); |
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.
see comment on L58
foreach my $config (@{ $params }) { | ||
my $rs_backup = $self->db->resultset('Cachegroup')->search( { id => $config->{fallbackId} } )->single(); | ||
if ( !defined($rs_backup) ) { | ||
&log( $self, "ERROR Backup config: No such Cache Group $config->{fallbackId}"); |
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.
see comment on L58
} | ||
|
||
if ( ($rs_backup->type->name ne "EDGE_LOC") ) { | ||
&log( $self, "ERROR Backup config: $config->{name} is not EDGE_LOC"); |
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.
see comment on L58
@@ -57,6 +57,36 @@ and (st.name = 'REPORTED' or st.name = 'ONLINE' or st.name = 'ADMIN_DOWN') | |||
if ttype == RouterTypeName { | |||
routerLocs[cachegroup] = latlon | |||
} else { | |||
primaryCacheId := "" |
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.
rather than re-querying the cachegroup's ID here, you should just update the query on L35 to also select cg.id
and scan that into a variable.
In fact, you might even be able to eliminate the query on L65 altogether by modifying the query on L35 to include a subquery. Something like:
select cg.name, ..., ARRAY(select c.name from cachegroup_fallbacks cgf join cachegroup c on c.id = cgf.backup_cg where cgf.primary_cg = cg.id) ... from ...
I haven't tried that query out, but I think it's worth a shot rather than running an extra query per cachegroup. If it's possible, you should be able to scan that result into a slice of strings and just iterate over it.
return nil, nil, errors.New("Failed while retrieving from cachegroup: " + err.Error()) | ||
} | ||
|
||
dbRows, err := db.Query(`select backup_cg from cachegroup_fallbacks where primary_cg = $1 order by set_order`, primaryCacheId) |
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 can use a join
here and remove the extra query on L79:
select cgf.backup_cg, c.name from cachegroup_fallbacks cgf join cachegroup c on c.id = cgf.backup_cg
@@ -0,0 +1,38 @@ | |||
/* |
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.
this file will need renamed again because another migration was recently merged
|
||
index := 0 | ||
for dbRows.Next() { | ||
backup_id := "" |
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.
in golang the typical naming style is to use camelcase, i.e. backupID
lib/go-tc/cachegroupfallback.go
Outdated
@@ -20,33 +20,33 @@ package tc | |||
* under the License. | |||
*/ | |||
|
|||
// A List of CACHEGROUPFALLBACKs Response | |||
// swagger:response CACHEGROUPFALLBACKsResponse | |||
// A List of cachegroupFallbacks Response |
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.
The c
and g
should be capitalized to match the rest of the CacheGroup
structs (capitalizing the first letter is most important in Go because it makes the struct exportable).
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.
Addressed.
@@ -49,20 +49,20 @@ and (st.name = 'REPORTED' or st.name = 'ONLINE' or st.name = 'ADMIN_DOWN') | |||
|
|||
for rows.Next() { | |||
cachegroup := "" | |||
primaryCacheID := "" |
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.
kind of a nitpick, but I think this should be primaryCacheID := 0
to match the int DB type
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.
Addressed.
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.
alright I think everything I've suggested has been addressed, but you'll need to git rebase master
this branch before it can be merged.
Tomorrow I'll try to find the time to pull this down and give it a whirl.
Contains the following changes: Traffic Router - Backup edge configuration parsing and decision making Traffic Ops - Mojolicious Perl CRUD APIs Address comments from Eric and Jeremy Addressing Dylan's comment on avoiding nested routes Addessing Dylan's comment on POSt Request / Response . API endpoints changes based on Jeremey's suggestion Resolved conflict in traffic_ops.rst Addressing Jeremy's comment on GET endpoint's return statements. Changes: 1. POST - Add new fallbacks. 2. PUT - Update existing fallbacks. Renamed 20180321000000_cache_group_fallback.sql -> 20180521000000_cache_group_fallback.sql
…achegroup_fallbacks.rst to docs/source/api/v12
…up APIs 2. Validating fallback inputs
1. Avoiding multiple DB querries using Join 2. &log to error logs
… 2. GoLang naming conventions
@rawlinp rebased |
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.
Tested out the API changes, found only some nits that can easily be remedied in the golang version when written.
However, the golang CRConfig generation needs fixed before this can be merged. I still need to test the TR changes and will update when done.
@@ -32,7 +32,7 @@ func makeLocations(cdn string, db *sql.DB) (map[string]tc.CRConfigLatitudeLongit | |||
|
|||
// TODO test whether it's faster to do a single query, joining lat/lon into servers | |||
q := ` | |||
select cg.name, t.name as type, cg.latitude, cg.longitude from cachegroup as cg | |||
select cg.name, cg.id, t.name as type, cg.latitude, cg.longitude from cachegroup as cg |
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 need to also select cg.fallback_to_closest here and scan the value into a var fallbackToClosest *bool
. If it's null, set BackupLocations.FallbackToClosest
below to true. Otherwise, set it to the dereferenced value.
Also, I noticed the CRConfig generated sets the value of fallbackToClosest
to a string rather than a boolean. Since booleans are an actual type in Go, I'm thinking we should set the values to booleans rather than strings and make sure Traffic Router handles that properly.
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.
I took a look and found a bunch of bools which gets written as string in this particular part. For example=> sslEnabled. Do we need to modify it for FallbackToClosest?
I will take a look at parsing FallbackToClosest and make changes.
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.
I think the string boolean thing might have stemmed from Perl not having real booleans. Now that it's been migrated to Go, we could use real booleans in the JSON. But since there are a bunch of string bools in the CRConfig already, I guess it's better to be consistent and keep it as a string bool.
if (closestCacheLocation != null) { | ||
LOGGER.debug("Got closest CZ cache group " + closestCacheLocation.getId() + " for " + ip + ", ds " + deliveryServiceId); | ||
if (track != null) { | ||
track.setFromBackupCzGroup(true); |
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 do we set this to true here? If we reach this point, there were no available backup cachegroups (or none configured), so we shouldn't track it as from a backup cachegroup, right?
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.
The cache which gets selected in this cache is not a primary one. This is again a backup cache configured via Coordinates and hence it gets tracked as backup.
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.
Ok, I can agree with that. It would be useful to track those occurrences as "backup hits".
Finished testing the TR changes; they still look good except for my question about the tracking. |
return nil, nil, errors.New("Error scanning cachegroup: " + err.Error()) | ||
} | ||
if ttype == RouterTypeName { | ||
routerLocs[cachegroup] = latlon | ||
} else { | ||
q := `select cachegroup.name from cachegroup_fallbacks | ||
join cachegroup on cachegroup_fallbacks.backup_cg = cachegroup.id | ||
and cachegroup_fallbacks.primary_cg = $1 |
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.
I missed this in my previous review, but this query is missing order by cachegroup_fallbacks.set_order
. Without this the set_order
ordering is not enforced.
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.
Right. I missed that. Addressed.
…ed properly in GOLang implementation
i "think" the requested changes were made but not really sure
Yes. The changes requested for edgeLocations.go for CRConfig were addressed. |
[Issue 1907] Backup edge cache group TO API / TR cr-config changes
#1907
Contains the following changes:
Traffic Router - Backup edge configuration parsing and decision making code changes
Traffic Ops - Mojolicious Perl CRUD APIs
This is the initial version of code. Only minimal testing has been done. Will run more cases and update. Hosting it in advance to get review comments :-)