Upgrading Tutor for Koa

As anyone managed to get Notes to work with open-release/koa.test01? I’m getting the following stacktrace when attempting to save a new note:

notes_1          | POST http://elasticsearch:9200/_bulk?refresh=true [status:400 request:0.002s]                                                     [32/1413]
notes_1          | Internal Server Error: /api/v1/annotations/1/                                                                                              
notes_1          | Traceback (most recent call last):                                                                                                         
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/exception.py", line 34, in inner                                       
notes_1          |     response = get_response(request)                                                                                                       
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/base.py", line 115, in _get_response                                   
notes_1          |     response = self.process_exception_by_middleware(e, request)                                                                            
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/core/handlers/base.py", line 113, in _get_response                                   
notes_1          |     response = wrapped_callback(request, *callback_args, **callback_kwargs)                                                                
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/views/decorators/csrf.py", line 54, in wrapped_view                                  
notes_1          |     return view_func(*args, **kwargs)                                                                                                      
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/views/generic/base.py", line 71, in view                                             
notes_1          |     return self.dispatch(request, *args, **kwargs)                                                                                         
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/rest_framework/views.py", line 505, in dispatch                                             
notes_1          |     response = self.handle_exception(exc)                                                                                                  
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/rest_framework/views.py", line 465, in handle_exception                                     
notes_1          |     self.raise_uncaught_exception(exc)                                                                                                     
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/rest_framework/views.py", line 476, in raise_uncaught_exception                             
notes_1          |     raise exc                                                                                                                              
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/rest_framework/views.py", line 502, in dispatch                                             
notes_1          |     response = handler(request, *args, **kwargs)                                                                                           
notes_1          |   File "/openedx/edx-notes-api/notesapi/v1/views.py", line 559, in delete                                                                  
notes_1          |     note.delete()                                                                                                                          
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/db/models/base.py", line 919, in delete                                              
notes_1          |     return collector.delete()                                                                                                              
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/db/models/deletion.py", line 317, in delete                                          
notes_1          |     signals.post_delete.send(                                                                                                              
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/dispatch/dispatcher.py", line 173, in send                                           
notes_1          |     return [                                                                                                                               
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django/dispatch/dispatcher.py", line 174, in <listcomp>                                     
notes_1          |     (receiver, receiver(signal=self, sender=sender, **named))                                                                              
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django_elasticsearch_dsl/signals.py", line 72, in handle_delete                        
notes_1          |     registry.delete(instance, raise_on_error=False)                                                                                [0/1413]
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django_elasticsearch_dsl/registries.py", line 148, in delete
notes_1          |     self.update(instance, action="delete", **kwargs)
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django_elasticsearch_dsl/registries.py", line 141, in update
notes_1          |     doc().update(instance, **kwargs)
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django_elasticsearch_dsl/documents.py", line 195, in update
notes_1          |     return self._bulk(
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django_elasticsearch_dsl/documents.py", line 179, in _bulk
notes_1          |     return self.bulk(*args, **kwargs)
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/django_elasticsearch_dsl/documents.py", line 146, in bulk
notes_1          |     return bulk(client=self._get_connection(), actions=actions, **kwargs)
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/helpers/actions.py", line 360, in bulk
notes_1          |     for ok, item in streaming_bulk(client, actions, *args, **kwargs):
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/helpers/actions.py", line 281, in streaming_bulk
notes_1          |     for data, (ok, info) in zip(
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/helpers/actions.py", line 217, in _process_bulk_chunk
notes_1          |     for item in gen:
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/helpers/actions.py", line 166, in _process_bulk_chunk_error
notes_1          |     raise error
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/helpers/actions.py", line 205, in _process_bulk_chunk
notes_1          |     resp = client.bulk("\n".join(bulk_actions) + "\n", *args, **kwargs)
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/client/utils.py", line 139, in _wrapped
notes_1          |     return func(*args, params=params, headers=headers, **kwargs)
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/client/__init__.py", line 428, in bulk
notes_1          |     return self.transport.perform_request(
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/transport.py", line 345, in perform_request
notes_1          |     status, headers_response, data = connection.perform_request(
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/connection/http_urllib3.py", line 256, in perform_request
notes_1          |     self._raise_error(response.status, raw_data)
notes_1          |   File "/usr/local/lib/python3.8/dist-packages/elasticsearch/connection/base.py", line 287, in _raise_error
notes_1          |     raise HTTP_EXCEPTIONS.get(status_code, TransportError)(
notes_1          | elasticsearch.exceptions.RequestError: RequestError(400, 'ActionRequestValidationException[Validation Failed: 1: type is missing;]', 'ActionRequestValidationException[Validation Failed: 1: type is missing;]')

EDIT: this PR leads me to believe that notes was upgraded to use Elasticsearch 7. If this is true we will either have to make notes work with ES 1.5.2 or flag notes as incompatible with Koa :-/

EDIT 2: a third option would be to tag an earlier version of edx-notes-api for release with Koa. According to my experiments commit cc29e31 is compatible with the open-release/koa.test01 version of edx-platform.