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

Communication chat preview4 #16905

Merged
merged 16 commits into from
Mar 3, 2021
Merged

Communication chat preview4 #16905

merged 16 commits into from
Mar 3, 2021

Conversation

sarkar-rajarshi
Copy link
Member

@sarkar-rajarshi sarkar-rajarshi commented Feb 24, 2021

  • CommunicationUserIdentifier models added
  • create_chat_thread - returns CreateChatThreadResult instead of ChatThreadClient
  • add_participant - AddChatParticipantsResult -> tuple(ChatThreadParticipant, CommunicationError)
  • add_participants - AddChatParticipantsResult -> list(tuple(ChatThreadParticipant, CommunicationError))
  • CommunicationErrorResponseConverter added to cosolidate list(ChatThreadParticipant) and list(CommunicationError) into list(tuple(ChatThreadParticipant, CommunicationError))
  • CreateChatThreadResult -> attributes changed to
    • chat_thread -> ChatThread (no change)
    • Errors -> CreateChatThreadErrors -> list(tuple(ChatThreadParticipant, CommunicationError))
  • create_chat_thread -> thread_participants and repeatability_request_id changed to keyword arguments
  • Modify unit tests to capture method signature modifications
  • Modify e2e tests to capture method signature modifications
  • Update README.md
  • Add new test recordings

sacheun and others added 4 commits February 24, 2021 02:01
* Add generated chat code from new swagger

* Change to use new generated code

* Address PR Feedback

* Remove CommunicationUserIdentifierModel in identity,phone number package
* Replace identifier with rawId

* Change serilizer

* Replace indentifier with rawId in test code

* Sync models across modules

* fix typo in serizliser

* Rearrange imports

* Replace rawId with raw_id

* remove trailing newline

Co-authored-by: turalf <tufarhad@microsoft.com>
- CommunicationUserIdentifier models added
- create_chat_thread - returns CreateChatThreadResult instead of ChatThreadClient
- add_participant - docstring update AddChatParticipantsResult instead of None
- add_participants - docstring update AddChatParticipantsResult instead of None
@sarkar-rajarshi
Copy link
Member Author

@@ -500,14 +501,14 @@ async def add_participants(
self,
thread_participants: List[ChatThreadParticipant],
**kwargs
) -> None:
) -> AddChatParticipantsResult:
Copy link
Member

Choose a reason for hiding this comment

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

We should unpackage this result type. It's currently pretty hard to use...
If you could write a sample demonstrating what a customer has to do to:

  • Add 5 participants
  • Determine which 2 our of those 5 failed.
  • Re-attempt to add those 2 failures.

From their we can figure out the best response value here.

Copy link
Member Author

Choose a reason for hiding this comment

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

@annatisch something like this?

def _util_create_thread_participant(user, **kwargs) -> ChatThreadParticipant:
    """
    Create util or call the constructor of ChatThreadParticipant - same thing
    """
    return ChatThreadParticipant(
    user=user_id,
    display_name = kwargs.get('display_name', None),
    share_history_time = kwargs.get('share_history_time', None)
    )
	

def decide_if_needs_to_retried(invalid_participant) -> bool:
    """
    some logic to determine if this is needed to be retried or not
    """
    return True


if __name__=='__main__':
    # intialize identity client
    identity_client = CommunicationIdentityClient.from_connection_string(connection_string)
    
    # initialize and retrieve chat_thread_client
    refresh_options = CommunicationTokenRefreshOptions(token)
    chat_client = ChatClient(endpoint, CommunicationTokenCredential(refresh_options))
    topic = "some topic"
    participants = [ChatThreadParticipant(
            user=user, # whoever is creating the chat_thread
            display_name='name',
            share_history_time=datetime.utcnow()
        )]
    create_chat_thread_result = chat_client.create_chat_thread(topic, participants)
    chat_thread_client = chat_client.get_chat_thread_client(create_chat_thread_result.chat_thread.id)
    
    
    # initialize 3+2 participants
    users_for_sucesss = [identity_client.create_user() for i in range(3)] # create 3 users for success - type: List[CommunicationUserIdentifier]
    users_for_failures = [CommunicationUserIdentifier("some random id 1"), CommunicationUserIdentifier("some random id 2")] # create 2 users for failures - type: List[CommunicationUserIdentifier]
    
    # create ChatThreadParticipant objects
    participants_success = [_util_create_thread_participant(user) for user in users_for_sucesss]
    participants_failures = [_util_create_thread_participant(user) for user in users_for_failures]
    
    # add participants to chat thread
    thread_participants = [participants_success + participants_failures]
    add_chat_participants_result = chat_thread_client.add_participants(thread_participants)
    
    # verify if all participants have been added or not
    participants_to_retry = [] # in case of failure store participants to be retried - type: List[CommunicationUserIdentifier]
    
    if hasattr(add_chat_participants_result, 'errors') and \
            add_chat_participants_result.errors is not None:
        print("Error encountered in adding ", len(thread_participants), " participants")
        participant_failed_to_add = add_chat_participants_result.errors.invalid_participants
        
        for failed_participant in participant_failed_to_add:
            # failed_participant.target contains the user_id - type: str
            # For example, in this scenario the values would be either 'some random id 1' or 'some random id 2'
            print("Failed to add participant", failed_participant.target)
            
            if decide_if_needs_to_retried(failed_participant):
                participants_to_retry.append(CommunicationUserIdentifier(failed_participant.target))
    
    # if any user has been failed to be added, then retry
    if len(participants_to_retry) != 0:
        thread_participants = [_util_create_thread_participant(retry_user) for retry_user in participants_to_retry]
        add_chat_participants_result_retry = chat_thread_client.add_participants(thread_participants)
		

Copy link
Member

Choose a reason for hiding this comment

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

Wow that's lots of code... and a couple of red flags. If a customer ever has to call hasattr on the response of call, then we did something wrong :)

If we change the return type to: List[Tuple[ChatThreadParticipant, Optional[AddParticipantError]]
Then we could replace all this:

    add_chat_participants_result = chat_thread_client.add_participants(thread_participants)
    
    # verify if all participants have been added or not
    participants_to_retry = [] # in case of failure store participants to be retried - type: List[CommunicationUserIdentifier]
    
    if hasattr(add_chat_participants_result, 'errors') and \
            add_chat_participants_result.errors is not None:
        print("Error encountered in adding ", len(thread_participants), " participants")
        participant_failed_to_add = add_chat_participants_result.errors.invalid_participants
        
        for failed_participant in participant_failed_to_add:
            # failed_participant.target contains the user_id - type: str
            # For example, in this scenario the values would be either 'some random id 1' or 'some random id 2'
            print("Failed to add participant", failed_participant.target)
            
            if decide_if_needs_to_retried(failed_participant):
                participants_to_retry.append(CommunicationUserIdentifier(failed_participant.target))
    
    # if any user has been failed to be added, then retry
    if len(participants_to_retry) != 0:
        thread_participants = [_util_create_thread_participant(retry_user) for retry_user in participants_to_retry]
        add_chat_participants_result_retry = chat_thread_client.add_participants(thread_participants)

With just a couple of lines:

result = chat_thread_client.add_participants(thread_participants)
failed = [p for p, error in result if decide_if_needs_to_retried(error)]
retry = chat_thread_client.add_participants(failed)

Copy link
Member Author

Choose a reason for hiding this comment

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

@annatisch The following changes have been made

  • add_participant - AddChatParticipantsResult -> tuple(ChatThreadParticipant, CommunicationError)
  • add_participants - AddChatParticipantsResult -> list(tuple(ChatThreadParticipant, CommunicationError))
  • CreateChatThreadResult -> attributes changed to
    • chat_thread -> ChatThread (no change)
    • Errors -> CreateChatThreadErrors -> list(tuple(ChatThreadParticipant, CommunicationError))

- add_participant - AddChatParticipantsResult -> tuple(ChatThreadParticipant, CommunicationError)
- add_participants - AddChatParticipantsResult -> list(tuple(ChatThreadParticipant, CommunicationError))
- unit tests modified as per signature change
- CommunicationErrorResponseConverter added to cosolidate list(ChatThreadParticipant) and list(CommunicationError) into list(tuple(ChatThreadParticipant, CommunicationError))
- e2e tests modified as per signature change
…ls with ease

- CreateChatThreadResult -> attributes changed to
  - chat_thread -> ChatThread (no change)
  - Errors -> CreateChatThreadErrors -> list(tuple(ChatThreadParticipant, CommunicationError))
- create_chat_thread -> `thread_participants` and `repeatability_request_id` changed to keyword arguments
- Modify unit tests to capture method signature modifications
- Modify e2e tests to capture method signature modifications
Copy link
Member

@annatisch annatisch left a comment

Choose a reason for hiding this comment

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

Looking good - I think we're nearly there :)

@@ -478,14 +483,16 @@ def add_participant(
thread_participant, # type: ChatThreadParticipant
**kwargs # type: Any
):
# type: (...) -> None
# type: (...) -> tuple(ChatThreadParticipant, CommunicationError)
Copy link
Member

Choose a reason for hiding this comment

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

In the case of the single add_participant, we shouldn't return the error object - we should just raise an error.

Copy link
Member

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

@annatisch add_participant raises error - change implemented

Copy link
Member

@juancamilor juancamilor Mar 2, 2021

Choose a reason for hiding this comment

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

@annatisch are we ok with having this diverge in python ? I am ok if you are.
When we run this in that meeting, the answer was to leave it as is in case in the future any additional data is required back from that call. I don't see that coming but that was the decision.

Copy link
Member

Choose a reason for hiding this comment

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

@juancamilor - raising errors rather than returning them is Pythonic behaviour that I would expect to differ from .Net.
We can still return the ChatThreadParticipant object - when you say additional data, you mean other information outside of these two fields?

Copy link
Member

Choose a reason for hiding this comment

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

yes, something like extra headers is what Ted G mentioned, but I don't have any requirements yet to back it up.

tg-msft1
There aren't today, but maybe it'll come back with extra headers in the future?

Copy link
Member

Choose a reason for hiding this comment

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

@annatisch after today's review we will address all the changes on the next iteration (including the removal of this operation).

- Update README.md with modified signature
- Update samples with new method signatures
- Add test to detect invalid instantiation of AccessToken
- Minor documentation updates
- Modify unit tests to capture method signature modifications
- Modify e2e tests to capture method signature modifications
@juancamilor juancamilor merged commit 3683f00 into Azure:feature/communication-chat-preview4-comm-models Mar 3, 2021
juancamilor pushed a commit that referenced this pull request Mar 3, 2021
* [Communication] Generate identifier Models from new swagger (#16735)
* Add generated chat code from new swagger
* Address PR Feedback
* Remove CommunicationUserIdentifierModel in identity,phone number package
* Check schema of the object to determine the type [preview4] (#16838)
* Replace identifier with rawId
* Change serilizer
* Replace indentifier with rawId in test code
* Sync models across modules
* fix typo in serizliser
* Rearrange imports
* Replace rawId with raw_id
* remove trailing newline

Co-authored-by: turalf <tufarhad@microsoft.com>

* preview4 changes made + unit tests fixed

* Chat - preview4 changes
- CommunicationUserIdentifier models added
- create_chat_thread - returns CreateChatThreadResult instead of ChatThreadClient
- add_participant - docstring update AddChatParticipantsResult instead of None
- add_participants - docstring update AddChatParticipantsResult instead of None

* pylint-changes

* pylint changes

* Method signature changed for add_pariticipant and add_participants
- add_participant - AddChatParticipantsResult -> tuple(ChatThreadParticipant, CommunicationError)
- add_participants - AddChatParticipantsResult -> list(tuple(ChatThreadParticipant, CommunicationError))
- unit tests modified as per signature change
- CommunicationErrorResponseConverter added to cosolidate list(ChatThreadParticipant) and list(CommunicationError) into list(tuple(ChatThreadParticipant, CommunicationError))
- e2e tests modified as per signature change

* CreateChatThreadResult modified to handle partial errors in batch calls with ease
- CreateChatThreadResult -> attributes changed to
  - chat_thread -> ChatThread (no change)
  - Errors -> CreateChatThreadErrors -> list(tuple(ChatThreadParticipant, CommunicationError))
- create_chat_thread -> `thread_participants` and `repeatability_request_id` changed to keyword arguments
- Modify unit tests to capture method signature modifications
- Modify e2e tests to capture method signature modifications

* pylint-changes

* pylint fixes

* README.md update + pylint fixes

* test recordings added

* add_participant -> raises error
- Update README.md with modified signature
- Update samples with new method signatures
- Add test to detect invalid instantiation of AccessToken
- Minor documentation updates
- Modify unit tests to capture method signature modifications
- Modify e2e tests to capture method signature modifications

* pylint fixes

* cls removed from docstring + update_topic async refactored

* cls removed from docstring

Co-authored-by: Sam Cheung <sacheu@microsoft.com>
Co-authored-by: turalf <tural.ferhadov@gmail.com>
Co-authored-by: turalf <tufarhad@microsoft.com>

Co-authored-by: Sam Cheung <sacheu@microsoft.com>
Co-authored-by: turalf <tural.ferhadov@gmail.com>
Co-authored-by: turalf <tufarhad@microsoft.com>
iscai-msft added a commit to iscai-msft/azure-sdk-for-python that referenced this pull request Mar 3, 2021
…into http_request_json

* 'master' of https://github.com/Azure/azure-sdk-for-python: (147 commits)
  [text analytics] add perf tests (Azure#17060)
  Add cloud event to core (Azure#16800)
  [Perf] Small fixes to storage-blob (Azure#17055)
  [EG] Regenerate Code (Azure#17053)
  Scrub batch shared keys (Azure#17030)
  [Tables] Add SAS to tables (Azure#16717)
  T2 containerservice 2021 03 03 (Azure#17050)
  Addressing issues with CredScan (Azure#16944)
  Communication chat preview4 (Azure#16905) (Azure#17037)
  remove first query section (Azure#17033)
  [formrecognizer] temp disable sample tests until service bug fixed (Azure#17036)
  [device update] allow device update pylint failures (Azure#17034)
  fix build (Azure#17029)
  update artifact names for ALL packages to align with the actual package name
  Create azure-iot-nspkg (Azure#17026)
  [Communication]: SMS 1:N Messages, Custom Tags, and Idempotence (Azure#16836)
  Fixing credentials to use AAD (Azure#16885)
  T2 deviceupdate 2021 03 02 (Azure#17016)
  T2 cosmosdb 2021 02 23 (Azure#16875)
  T2 datadog 2021 03 02 (Azure#17004)
  ...
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.

5 participants