AzureFunctions에서 CosmosDB에 등록하는 AzureEventhubs의 Consumer 생성

GYAO의 ts입니다.
우리 팀은 올 퍼블릭 클라우드에서 Microservice Architecture을 채택한 차기 백엔드를 설계 중입니다.

경위



마지막 게시물 에서 PartitionKey를 설정하면 Eventhubs에 발행하는 이벤트의 순서성이 보장되었습니다.
그리고는 Functions로 Consumer를 작성해 CosmosDB의 Document를 괴롭히는 만.

하고 싶은 일



이벤트 발행되는 내용(body의 json)은 아래와 같이

이벤트
{
  "Id": "user1",
  "ContentsId": "content01",
  "Type": "ADD",
  "Time": 1500016145
}

Type은 ADD와 DELETE가 발행된다.
CosmosDB에는 Id를 Key로 한 문서가 아래와 같이 등록된다.
요점은 Contents 배열에 ADD 되거나 배열로부터 DELETE 된다.
※Pkey는 CosmosDB의 PartitionKey.

CosmosDB 문서
{
  "Contents": [
    {
      "ContentsId": "content01",
      "Time": 1500016145
    },
    {
      "ContentsId": "content02",
      "Time": 1500016162
    }
  ],
  "Pkey": "reserve",
  "id": "user1"
}

통합 설정



Document를 Id 검색해, 있을까 없는지로 거동이 바뀌어 오기 때문에, 아래와 같이 된다.


또, 이번은 CosmosDB에도 CosmosDB의 PartitionKey를 지정하고 있으므로, 아래와 같이 function.json으로 partitionKey를 지정해 주지 않으면 에러가 된다.

function.json

    {
      "type": "documentDB",
      "name": "inputDocument",
      "databaseName": "xxxxdb",
      "collectionName": "contents",
      "partitionKey": "reserve",
      "id": "{Id}",
      "connection": "xxxxdatabase_DOCUMENTDB",
      "direction": "in"
    },
    {
      "type": "documentDB",
      "name": "outputDocument",
      "databaseName": "xxxxdb",
      "partitionKey": "reserve",
      "collectionName": "contents",
      "createIfNotExists": false,
      "connection": "xxxxdatabase_DOCUMENTDB",
      "direction": "out"
    }

CosmosDB 입력 바인딩



이번에는 명시적으로 POCO에 바인딩.
#r "Newtonsoft.Json"

using System;
using System.Net;
using Newtonsoft.Json;

public class Input
{
    public string ContentsId { get; set; }
    public int Time { get; set; }
    public string Id { get; set; }
    public string Type { get; set; }
}

public class Content
{
    public string ContentsId { get; set; }
    public int Time { get; set; }
}

public class Document
{
    public List<Content> Contents { get; set; }
    public string Pkey { get; set; }
    public string id { get; set; }
}

Type은 ADD와 DELETE뿐이므로 Enum으로 하는 것이 좋다. 나중에 그렇게합니다.

ADD



첫회



Document 자체가 없기 때문에 작성한다.

    if (input.Type == "ADD" && inputDocument == null) 
    {
        var doc = new Document()
        {
            id = input.Id,
            Pkey = "reserve",
            Contents = new List<Content>()            
        };
        var content = new Content()
        {
            ContentsId = input.ContentsId,
            Time = input.Time
        };
        doc.Contents.Add(content);
        outputDocument = doc;
    }

처음이 아닌 경우(이미 Document가 있는 경우)



그냥 배열에 ADD만
    else if (input.Type == "ADD" && inputDocument != null)
    {
        var content = new Content()
        {
            ContentsId = input.ContentsId,
            Time = input.Time
        };
        inputDocument.Contents.Add(content);
        outputDocument = inputDocument;
    }

DELETE



remove만. 람다식은 아니지만.
    else if (input.Type == "DELETE" && inputDocument != null)
    {
        Content targetContent = inputDocument.Contents.Find(
               delegate(Content content) { return content.ContentsId == input.ContentsId; });
        inputDocument.Contents.Remove(targetContent);
        outputDocument = inputDocument;
    }


소감



순서성의 부분을 제외하면, 극히 단순한 일 밖에 하고 있지 않다.
Eventhubs의 PartitionKey와 CosmosDB의 PartitionKey가 있지만, 동일하게 해도 재미있을 것 같다고 생각했다. 새로운 서비스용으로 확장할 때 PartitionKey를 새롭게 만드는 것 같은 형태로 할까? 복잡하기 때문에 나중에 생각합시다. . .

좋은 웹페이지 즐겨찾기