Skip to content

Refactor api commands#3168

Merged
jerrypeng merged 11 commits intoapache:masterfrom
aahmed-se:refactorApiCommands
Dec 21, 2018
Merged

Refactor api commands#3168
jerrypeng merged 11 commits intoapache:masterfrom
aahmed-se:refactorApiCommands

Conversation

@aahmed-se
Copy link
Contributor

@aahmed-se aahmed-se commented Dec 12, 2018

We are deprecating the Response Object in favor data object responses.

Copy link
Member

@sijie sijie left a comment

Choose a reason for hiding this comment

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

it is unclear to me what is this PR for. please update the description with your motivation and what are the changes.

Copy link
Member

Choose a reason for hiding this comment

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

I don't understand why the return value was changed to void?

Copy link
Contributor

Choose a reason for hiding this comment

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

because there is no output that needs to be returned. If there is an error raising a RestException will trigger jetty to return the error message

Copy link
Member

Choose a reason for hiding this comment

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

but this is a breaking change no? How can old pulsar admin clients talk to new broker?

Copy link
Contributor

Choose a reason for hiding this comment

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

updateSink won't be a breaking change because the the response returned has no content just a 400 status code

Copy link
Member

Choose a reason for hiding this comment

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

let's not couple fixing typos with other changes.

Copy link
Member

Choose a reason for hiding this comment

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

please don't do this.

@aahmed-se
Copy link
Contributor Author

I didn't mark this ready for review yet.

@aahmed-se aahmed-se changed the title Refactor api commands (WIP) Refactor api commands Dec 13, 2018
Copy link
Contributor

Choose a reason for hiding this comment

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

This should return FunctionConfig

Copy link
Contributor

Choose a reason for hiding this comment

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

this should return a list

Copy link
Contributor

Choose a reason for hiding this comment

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

this should return something. Not sure if its String or byte[]

Copy link
Contributor

Choose a reason for hiding this comment

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

This should not return void

Copy link
Contributor

Choose a reason for hiding this comment

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

this should not return void

Copy link
Contributor

Choose a reason for hiding this comment

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

return SinkConfig

Copy link
Contributor

Choose a reason for hiding this comment

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

return list

Copy link
Contributor

Choose a reason for hiding this comment

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

return sourceconfig

Copy link
Contributor

Choose a reason for hiding this comment

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

return list

Copy link
Contributor

Choose a reason for hiding this comment

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

We should just have another method called getSinkInfo and it should return a SinkConfig not object

Copy link
Contributor

Choose a reason for hiding this comment

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

Same as my comment for Sink

Copy link
Contributor

Choose a reason for hiding this comment

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

Can you rename the function to throwUnavailableException

Copy link
Contributor

Choose a reason for hiding this comment

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

This should be FunctionConfig

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 not void

Copy link
Contributor

Choose a reason for hiding this comment

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

Not void

Copy link
Contributor

Choose a reason for hiding this comment

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

should return this value

when(mockedManager.containsFunction(eq(tenant), eq(namespace), eq(source))).thenReturn(false);

Response response = updateDefaultSource();
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

when(mockedManager.containsFunction(eq(tenant), eq(namespace), eq(source))).thenReturn(true);

Response response = updateDefaultSource();
assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

when(mockedManager.updateFunction(any(FunctionMetaData.class))).thenReturn(requestResult);

Response response = updateDefaultSource();
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

when(mockedManager.updateFunction(any(FunctionMetaData.class))).thenReturn(requestResult);

Response response = updateDefaultSource();
assertEquals(Status.INTERNAL_SERVER_ERROR.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

function,
null);

assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

when(mockedManager.containsFunction(eq(tenant), eq(namespace), eq(source))).thenReturn(false);

Response response = deregisterDefaultSource();
assertEquals(Status.NOT_FOUND.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

public void testRegisterFunctionNonexistantNamespace() throws Exception {
this.namespaceList.clear();
Response response = registerDefaultSource();
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

new Gson().toJson(sinkConfig),
null);

assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should still check status code

if (expectedError == null) {
assertEquals(Status.OK.getStatusCode(), response.getStatus());
} else {
assertEquals(Status.BAD_REQUEST.getStatusCode(), response.getStatus());
Copy link
Contributor

Choose a reason for hiding this comment

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

we should check status code

Add Status code Asserts
log.error("{} does not exist @ /{}/{}/{}", componentType, tenant, namespace, componentName);
return Response.status(Status.NOT_FOUND).type(MediaType.APPLICATION_JSON)
.entity(new ErrorData(String.format("%s %s doesn't exist", componentType, componentName))).build();
throw new RestException(Status.BAD_REQUEST, String.format("%s %s doesn't exist", componentType, componentName));
Copy link
Contributor

Choose a reason for hiding this comment

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

the return code should be not found


if (null == worker().getStateStoreAdminClient()) {
return getStateStoreUnvailableResponse();
getStateStoreUnvailableResponse();
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be a return statement

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We are throwing an exception why would there be a return value

Rename getStateStoreUnvailableResponse
public Response getFunctionInfo(final String tenant,
final String namespace,
final String componentName) {
public FunctionConfig getFunctionInfo(final String tenant,
Copy link
Contributor

Choose a reason for hiding this comment

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

This function should get moved out into org.apache.pulsar.functions.worker.rest.api.FunctionImpl

@srkukarni
Copy link
Contributor

run integration tests

@srkukarni
Copy link
Contributor

@sijie does this pr look good to you now?

Copy link
Member

@sijie sijie left a comment

Choose a reason for hiding this comment

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

since it is changing the rest api, please add an integration test to make sure old admin client can talk to new brokers.

if the old admin client can't talk to new brokers, it is breaking BC. then you should consider adding v3 api instead of changing the v2 api.

@ApiResponses(value = { @ApiResponse(code = 400, message = "Invalid request"),
@ApiResponse(code = 404, message = "The function does not exist"),
@ApiResponse(code = 500, message = "Internal server error") })
@ApiResponse(code = 404, message = "The function does not exist"),
Copy link
Member

Choose a reason for hiding this comment

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

please revert the indent change here. because @apiresponse is not a separate annotation, but it is part of @ApiResponses

Copy link
Member

Choose a reason for hiding this comment

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

but this is a breaking change no? How can old pulsar admin clients talk to new broker?

);
} catch (RestException re){
assertEquals(re.getResponse().getStatusInfo(), Response.Status.BAD_REQUEST);
throw re;
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place. you already catch the exception here, you should also validate @Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Tenant is not provided") rather than rethrowing the exception and use a different way to do assertions.

topicsToSerDeClassName,
className,
parallelism,
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Namespace is not provided")
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place.

topicsToSerDeClassName,
className,
parallelism,
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Sink Name is not provided")
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place.

@Test
public void testRegisterSinkZeroParallelism() throws IOException {
testRegisterSinkMissingArguments(
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Sink parallelism should positive number")
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place.

@Test
public void testRegisterSinkHttpUrl() throws IOException {
testRegisterSinkMissingArguments(
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Invalid Sink Jar")
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place.

}

@Test
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "Sink test-sink already exists")
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place.

}

@Test
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "upload failure")
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place.

}

@Test
@Test(expectedExceptions = RestException.class, expectedExceptionsMessageRegExp = "sink failed to register")
Copy link
Member

Choose a reason for hiding this comment

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

keep all assertions in one place.

@srkukarni
Copy link
Contributor

@sijie I'm not sure if this pr breaks backwards compatibility. Its not changing any return types.

@sijie
Copy link
Member

sijie commented Dec 21, 2018

@srkukarni I would prefer some forms of tests to ensure it doesn't really break BC, because breaking BC is a really bad behavior to users.

Copy link
Member

@sijie sijie left a comment

Choose a reason for hiding this comment

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

@srkukarni @jerrypeng @aahmed-se I have commented a few examples that return types are changes. Are you guys sure those doesn't break BC?

@Path("/{tenant}/{namespace}")
public Response listSink(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace) {
public List<String> listSink(final @PathParam("tenant") String tenant,
Copy link
Member

Choose a reason for hiding this comment

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

this is returning List<String> instead of Response. doesn't it break the BC?

public Response getSinkInfo(final @PathParam("tenant") String tenant,
final @PathParam("namespace") String namespace,
final @PathParam("sinkName") String sinkName)
public SinkConfig getSinkInfo(final @PathParam("tenant") String tenant,
Copy link
Member

Choose a reason for hiding this comment

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

This is changing from Response to SinkConfig, doesn't it break the BC?

final @PathParam("sourceName") String sourceName) throws IOException {
return source.getFunctionInfo(
tenant, namespace, sourceName);
public SourceConfig getSourceInfo(final @PathParam("tenant") String tenant,
Copy link
Member

Choose a reason for hiding this comment

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

This changes Response to SourceConfig, doesn't it break BC?

@jerrypeng
Copy link
Contributor

jerrypeng commented Dec 21, 2018

@sijie I think we have already broken backwards compatibility with getFunctionInfo, getStatus, getStats endpoints in previous PRs. To maintain backwards compatibility, I would suggest 1) merge this PR, 2) go back and move all the changes for those endpoints to V3, 3) add the old endpoints back to V2. Add tests to make sure old clients can still talk with V2 endpoints.

@aahmed-se
Copy link
Contributor Author

I will make the changes for the assert statements not sure if we want to invest in BC tests at this time.

@sijie
Copy link
Member

sijie commented Dec 21, 2018

getFunctionInfo, getStatus, getStats endpoints

can you gusy come up a list of endpoints that are added in 2.3.0 and those were changed in 2.3.0, before we make any decisions?

If they are new endpoints added in 2.3.0, they are okay.
But if they are old endpoints in 2.2.0 and changed in 2.3.0, we should revert those changes and add new endpoints.

@aahmed-se
Copy link
Contributor Author

There is low chance on BC breaking , I am directly returning the object to be serialized by jersey rather than doing it explicitly.

@jerrypeng
Copy link
Contributor

@sijie The PR actually doesn’t change the output of any of the endpoints, its just returning the actual object to be serialized by jersey to json instead of doing that explicitly ourselves. This PR will also make it more clear what is actually returned so it will be easier not to break backwards compatibility since currently many endpoints are just returning a Response object which is unclear what is contained within.

However, after this PR lets make sure that no changes have being introduced in the admin api so that 2.3 would break backwards compatibility for 2.2

@jerrypeng jerrypeng merged commit 867d924 into apache:master Dec 21, 2018
@aahmed-se aahmed-se deleted the refactorApiCommands branch December 21, 2018 02:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants