Procesamiento de flujo dinamo de AWS utilizando Go lambda

CorePress2024-01-25  10

Estoy usando una función AWS Lambda escrita en Go with Dynamo Stream, pero no veo ninguna manera de poder organizar el antiguo & nueva imagen a mi estructura porque devuelve la imagen como map[string]DynamoDBAttributeValue. Puedo verificar la clave individual y luego asignarla a mi estructura una por una, pero ¿hay una manera directa de llegar a Marshall directamente?

func HandleRequest(ctx context.Context, event events.DynamoDBEvent) {
    for _, record := range event.Records {

        var newStruct models.MyStruct // want to marshall newImage in this struct

        logger.Debugf("New: %#v", record.Change.NewImage)
    }
}

ACTUALIZACIÓN: Este es el evento DynamoDBEvent personalizado que estoy usando ahora:

type DynamoDBEvent struct {
    Records []DynamoDBEventRecord `json:"Records"`
}

type DynamoDBEventRecord struct {
    AWSRegion      string                       `json:"awsRegion"`
    Change         DynamoDBStreamRecord         `json:"dynamodb"`
    EventID        string                       `json:"eventID"`
    EventName      string                       `json:"eventName"`
    EventSource    string                       `json:"eventSource"`
    EventVersion   string                       `json:"eventVersion"`
    EventSourceArn string                       `json:"eventSourceARN"`
    UserIdentity   *events.DynamoDBUserIdentity `json:"userIdentity,omitempty"`
}

type DynamoDBStreamRecord struct {
    ApproximateCreationDateTime events.SecondsEpochTime             `json:"ApproximateCreationDateTime,omitempty"`
    Keys                        map[string]*dynamodb.AttributeValue `json:"Keys,omitempty"`
    NewImage                    map[string]*dynamodb.AttributeValue `json:"NewImage,omitempty"`
    OldImage                    map[string]*dynamodb.AttributeValue `json:"OldImage,omitempty"`
    SequenceNumber              string                              `json:"SequenceNumber"`
    SizeBytes                   int64                               `json:"SizeBytes"`
    StreamViewType              string                              `json:"StreamViewType"`
}

pude hacerlo escribiendo registros de eventos DynamoDBEvent personalizados

- shashank sachan

29/03/2021 a las 14:09

¿Podemos compartir algún código como respuesta para demostrar cómo utilizó DynamoDBEvent para resolver el problema? Esto podría resultar útil para futuros lectores.

- Jeremy Caney

29/03/2021 a las 18:12

Se agregó el evento personalizado

- Shashank Sachan

14 de abril de 2021 a las 12:41



------------------------------------

Desafortunadamente, todavía no existe una forma elegante, por lo que debe verificar cada par clave/valor y asignarlos a su estructura.

PD: como azúcar pequeña, puedes usar la función FromDynamoDBMap de este paquete y trabajar con map[string]interface{}, no con map[string]events.DynamoDBAttributeValue, que es mucho más fácil.



------------------------------------

He creado una solución para el problema. Esto fue crucial para mi implementación ya que mi implementación utiliza claves personalizadas.

Desafortunadamente, el tipo Número debe convertirse a Float64 paraasegúrese de que no se pierda.

Esto dará como resultado una estructura completamente utilizable contra el conjunto de cambios. Es posible que necesites un mapa de tus modelos y un campo conocido

Uso
newResult, _ := UnmarshalStreamImage(record.Change.NewImage)
newMarshal, _ := attributevalue.MarshalMap(newResult)
model := SomeModel{}
err := attributevalue.UnmarshalMap(newMarshal, &model)
Código de función



// UnmarshalStreamImage converts events.DynamoDBAttributeValue to struct
func UnmarshalStreamImage(attribute map[string]events.DynamoDBAttributeValue) (map[string]interface{}, error) {
    baseAttrMap := make(map[string]interface{})
    for k, v := range attribute {
        baseAttrMap[k] = extractVal(v)
    }
    return baseAttrMap, nil
}

func extractVal(v events.DynamoDBAttributeValue) interface{} {
    var val interface{}
    switch v.DataType() {
    case events.DataTypeString:
        val = v.String()
    case events.DataTypeNumber:
        val, _ = v.Float()
    case events.DataTypeBinary:
        val = v.Binary()
    case events.DataTypeBoolean:
        val = v.Boolean()
    case events.DataTypeNull:
        val = nil
    case events.DataTypeList:
        list := make([]interface{}, len(v.List()))
        for _, item := range v.List() {
            list = append(list, extractVal(item))
        }
        val = list
    case events.DataTypeMap:
        mapAttr := make(map[string]interface{}, len(v.Map()))
        for k, v := range v.Map() {
            mapAttr[k] = extractVal(v)
        }
        val = mapAttr
    case events.DataTypeBinarySet:
        set := make([][]byte, len(v.BinarySet()))
        for _, item := range v.BinarySet() {
            set = append(set, item)
        }
        val = set
    case events.DataTypeNumberSet:
        set := make([]string, len(v.NumberSet()))
        for _, item := range v.NumberSet() {
            set = append(set, item)
        }
        val = set
    case events.DataTypeStringSet:
        set := make([]string, len(v.StringSet()))
        for _, item := range v.StringSet() {
            set = append(set, item)
        }
        val = set
    }
    return val
}```

Su guía para un futuro mejor - libreflare
Su guía para un futuro mejor - libreflare