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

Add a new base type EventGridEventData for all system event data types #3309

Closed
wants to merge 3 commits into from

Conversation

kalyanaj
Copy link
Contributor

@kalyanaj kalyanaj commented Jun 26, 2018

This PR introduces a new base type EventGridEventData for all system event data types. Currently, there's no common base type across EventGrid event data across different publishers (e.g. Storage / MediaServices / IoTHub / ARM etc.). We now define this base type called EventGridEventData and use the allOf semantics to tie the different event data types together. This should be a non-breaking change (verified for C# and Python) as the newly base type doesn't have any properties. Also, added the generate-empty-classes to true in the global configuration.

PR information

  • The title of the PR is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For information on cleaning up the commits in your pull request, see this page.
  • Except for special cases involving multiple contributors, the PR is started from a fork of the main repository, not a branch.
  • If applicable, the PR references the bug/issue that it fixes.
  • Swagger files are correctly named (e.g. the api-version in the path should match the api-version in the spec).

Quality of Swagger

@AutorestCI
Copy link

AutorestCI commented Jun 26, 2018

Automation for azure-sdk-for-java

Nothing to generate for azure-sdk-for-java

@AutorestCI
Copy link

AutorestCI commented Jun 26, 2018

Automation for azure-sdk-for-python

A PR has been created for you:
Azure/azure-sdk-for-python#2814

@AutorestCI
Copy link

AutorestCI commented Jun 26, 2018

Automation for azure-sdk-for-ruby

Encountered a Subprocess error: (azure-sdk-for-ruby)

Command: ['/usr/local/bin/autorest', '/tmp/tmp4wcrfazu/rest/specification/eventgrid/data-plane/readme.md', '--multiapi', '--ruby', '--ruby-sdks-folder=/tmp/tmp4wcrfazu/sdk', '[email protected]/[email protected]', '--version=preview']
Finished with return code 1
and output:

AutoRest code generation utility [version: 2.0.4280; node: v7.10.1]
(C) 2018 Microsoft Corporation.
https://aka.ms/autorest
   Loading AutoRest core      '/root/.autorest/@[email protected]/node_modules/@microsoft.azure/autorest-core/dist' (2.0.4280)
   Loading AutoRest extension '@microsoft.azure/autorest.ruby' (3.0.20->3.0.20)
   Loading AutoRest extension '@microsoft.azure/autorest.modeler' (2.1.22->2.1.22)
Processing batch task - {"tag":"package-2018-01"} .
FATAL: The schema's 'StorageBlobCreatedEventData' ancestors should have at lease one property
FATAL: AutoRest.Core.Logging.CodeGenerationException: The schema's 'StorageBlobCreatedEventData' ancestors should have at lease one property
   at AutoRest.Modeler.SwaggerModeler.BuildCompositeTypes() in C:\Users\ci\AppData\Local\Temp\PUBLISHv6236\20_20171009T223650\autorest.modeler\src\SwaggerModeler.cs:line 312
   at AutoRest.Modeler.SwaggerModeler.Build(ServiceDefinition serviceDefinition) in C:\Users\ci\AppData\Local\Temp\PUBLISHv6236\20_20171009T223650\autorest.modeler\src\SwaggerModeler.cs:line 69
   at AutoRest.Modeler.Program.<ProcessInternal>d__2.MoveNext() in C:\Users\ci\AppData\Local\Temp\PUBLISHv6236\20_20171009T223650\autorest.modeler\src\Program.cs:line 53
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at NewPlugin.<Process>d__15.MoveNext()
FATAL: ruby/modeler - FAILED
FATAL: Error: Plugin modeler reported failure.
Process() cancelled due to exception : Plugin modeler reported failure.
Failure during batch task - {"tag":"package-2018-01"} -- Error: Plugin modeler reported failure..
  Error: Plugin modeler reported failure.

@AutorestCI
Copy link

AutorestCI commented Jun 26, 2018

Automation for azure-sdk-for-node

A PR has been created for you based on this PR content.

Once this PR will be merged, content will be added to your service PR:
Azure/azure-sdk-for-node#2800

@AutorestCI
Copy link

AutorestCI commented Jun 26, 2018

Automation for azure-sdk-for-go

A PR has been created for you:
Azure/azure-sdk-for-go#2128

@joshgav
Copy link

joshgav commented Jun 26, 2018

cc @marstr

@@ -119,9 +119,19 @@
}
}
},
"EventGridEventData": {
Copy link
Member

Choose a reason for hiding this comment

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

What is the intent with this type? From the description it sounds like it's intended to be polymorphic? If that's the case have you looked into using discriminated types?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea behind the new EventGridEventData type is just to serve as a common base across all the first party eventdata types. More info on how I arrived at this is in approach 2 below.

The existing EventGridEvent type contains the common properties of an event (id, eventType, eventTime etc.) + a "data" portion which is of type object. With this, there are two possible approaches:

Approach 1. [Evaluated but not used]: Specify the eventType property in EventGridEvent as the discriminator (e.g. "Microsoft.Storage.BlobCreated" -> StorageBlobCreatedEvent, "Microsoft.Storage.BlobDeleted" -> StorageBlobDeletedEvent. Remove the "Data" property from the EventGridEvent type and have new types such as StorageBlobCreatedEvent which contain a property called Data which is of the appropriate type such as StorageBlobCreatedEventData. However, in this approach, handling for 3rd party types is not as seamless: if have a 3rd party application publishes an event with eventType "Contoso.Items.ItemReceived", they will have to have special attributes/annotations for their custom type in order to fit into this discriminator model. Further, for 3rd party events, we also support other types for the data (strings/numeric/arrays etc.), which doesn't work well with this approach. In addition, we have already GA'ed with the approach where EventGridEvent contains a Data property, so I guess it will also be a breaking change to remove it now (in order to add it to the inherited types).

Approach 2 (Current approach): The "Data" property is part of the EventGridEvent type itself and it is of type object. The consuming code calls an EventGrid SDK function to deserialize EventGridEvents. This SDK function will internally maintain a mapping of eventType string -> eventData type and will use this mapping to look at the eventType property in the event(e.g. "Microsoft.Storage.BlobCreated") and will deserialize the Data property into the right data type such as StorageBlobCreatedEventData. The same SDK function will also support adding custom 3rd party mappings (e.g. "Contoso.Items.ItemReceived" -> typeof(ContosoItemReceivedEventData)). While creating this SDK function, I wanted to have a unit test to verify that for every system eventData type, there exists a corresponding mapping in this internal dictionary. However, without a common base class such as this newly introduced EventGridEventData, there's no way to programmatically determine which are all the eventData classes. This is the intent behind adding this new type.

Please let me know you have questions/comments.

Copy link
Member

Choose a reason for hiding this comment

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

So if I understand correctly, the fact that some type derives from EventGridEventData indicates means that it's an eventData class correct (presumably you use reflection to make this determination)? It seems like a very C#-specific implementation. E.g. for Go this just generates a useless type that pollutes the package namespace (see this). I don't know how this would work in other languages.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, the fact that a type derives from EventGridEventData indicates means that it's an eventData class. For Go, if this type is not useful, can we customize the code generation to not generate it (e.g. through the --generate-empty-classes option)? For Java, Python, and C# this would show up as a base class.

Copy link
Member

Choose a reason for hiding this comment

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

Presumably there's a way to omit it but ideally we should have a solution that works for all languages. How do you plan on supporting this in Go?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My understanding from speaking to @marstr earlier this week was that this was kind of expected for Go (since the base type doesn't have any properties, nothing will be copied over). Do you or @marstr have any suggestions on if/how this can be solved in Go?

Copy link
Member

Choose a reason for hiding this comment

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

What code will be used to programmatically determine the eventData classes, is this something your team will provide? Do you have a sample you can share that consumes this new functionality?

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 think we can close this for now and bring it back if/when there are additional product scenarios.

Currently, it is only unit test code for a SDK function to verify that there exists a mapping for each such eventData type (for which it uses reflection to determine the count of these classes) - the idea was to catch bugs whereby somebody introduces a new eventData type but forgets to add it to the mapping dictionary.

@kalyanaj kalyanaj closed this Jul 2, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants