meraki / dashboard-api-go

Dashboard API for Golang
MIT License
19 stars 7 forks source link

Refactor api client to adhere to rate limits #25

Closed danischm closed 3 months ago

danischm commented 3 months ago

This PR introduces the following changes/enhancements, while trying to retain the current structure and implementation as much as possible:

TODO: Update remaining services to use new Get/Post/Put/Delete functions using existing code generation tools.

fmunozmiranda commented 3 months ago
Remove NewClientNoAuth() and NewClientWithOptionsNoAuth() as the client does not authenticate actively anyway and the current implementation can be confusing, as you would end up with a client without a User-Agent string defined and no retries enabled

This point was not considered, since it has its function to create a client from environment variables.

fmunozmiranda commented 3 months ago

Please don´t remove it. It is necesary for client creation with env vars.

If you can put ratelimiter.Wait(1) directly in function, and not use new POST, GET, DELETE. PUT methods it would be better for us, because in that way it doesn´t represents a big change in or generation tool.

danischm commented 3 months ago

Please don´t remove it. It is necesary for client creation with env vars.

Where is it being used? Neither NewClientNoAuth() nor NewClientWithOptionsNoAuth() is being used in the provider. If you would use them you would end up with a client that does not have a User-Agent string defined and also the resty retry mechanism is not configured which makes the client behave differently than the one created by NewClient() or NewClientWithOptions() functions.

danischm commented 3 months ago

If you can put ratelimiter.Wait(1) directly in function, and not use new POST, GET, DELETE. PUT methods it would be better for us, because in that way it doesn't represents a big change in or generation tool.

The reason I created this functions is to have a place to later introduce more granular rate limiting controls as the server side rate limiting is done per organization and on the other hand it reduces the boilerplate code in the services implementations. It should actually simplify the code generation as you would only need to replace the result and body data structure names in a single line of code.

fmunozmiranda commented 3 months ago

These are used internally by the api_client, to avoid confusion, in the readme, you have the way in which the provider is used.

https://github.com/meraki/dashboard-api-go/tree/develop?tab=readme-ov-file#parameters

danischm commented 3 months ago

These are used internally by the api_client, to avoid confusion, in the readme, you have the way in which the provider is used.

Both these functions shown in the readme (NewClient() or NewClientWithOptions()) are still there and work as before. I did not remove them.

fmunozmiranda commented 3 months ago

If you can put ratelimiter.Wait(1) directly in function, and not use new POST, GET, DELETE. PUT methods it would be better for us, because in that way it doesn't represents a big change in or generation tool.

The reason I created this functions is to have a place to later introduce more granular rate limiting controls as the server side rate limiting is done per organization and on the other hand it reduces the boilerplate code in the services implementations. It should actually simplify the code generation as you would only need to replace the result and body data structure names in a single line of code.

Yes, I understand what are you saying, but for us is better to have it separated, in case we have to custom one of them, please, help us with that.

fmunozmiranda commented 3 months ago

These are used internally by the api_client, to avoid confusion, in the readme, you have the way in which the provider is used.

Both these functions shown in the readme (NewClient() or NewClientWithOptions()) are still there and work as before. I did not remove them.

Ok, I think we can allow it. Thank you

danischm commented 3 months ago

Yes, I understand what are you saying, but for us is better to have it separated, in case we have to custom one of them, please, help us with that.

I can update the code as you said, but I would suggest to still keep the generic Get/Post/Put/Delete functions as they could be useful also outside the current services implementation. Would you agree?

fmunozmiranda commented 3 months ago

Yes, I understand what are you saying, but for us is better to have it separated, in case we have to custom one of them, please, help us with that.

I can update the code as you said, but I would suggest to still keep the generic Get/Post/Put/Delete functions as they could be useful also outside the current services implementation. Would you agree?

Ok.

fmunozmiranda commented 3 months ago

If you can set as configurable, the requestPerSecond client can do, would be perfect too

danischm commented 3 months ago

If you can set as configurable, the requestPerSecond client can do, would be perfect too

But just via environment variable or also include it as a mandatory parameter in the NewClientWithOptions() function?

fmunozmiranda commented 3 months ago

Both, I think is better

fmunozmiranda commented 3 months ago

You can have it like a default of 10 if user don´t specify

danischm commented 3 months ago

Ok. If we change NewClientWithOptions() to something like this:

func NewClientWithOptions(baseURL string, dashboardApiKey string, debug string, sslVerify string, requestsPerSecond int)

Which is not ideal as the user would need to know what the appropriate value is and we could not really make use of a default value. Another option is to introduce a separate function:

func NewClientWithOptionsAndRequests(baseURL string, dashboardApiKey string, debug string, sslVerify string, requestsPerSecond int)

Or make use of the Functional Optionals Pattern.

fmunozmiranda commented 3 months ago

I think if we have this:

func NewClientWithOptionsAndRequests(baseURL string, dashboardApiKey string, debug string, sslVerify string, requestsPerSecond int)

And something like:

client.SetRequestPerSecond(i int)

Would be perfect-