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 example usage of IterWithTable. #242

Open
tamccall opened this issue Jul 16, 2024 · 6 comments
Open

Add example usage of IterWithTable. #242

tamccall opened this issue Jul 16, 2024 · 6 comments

Comments

@tamccall
Copy link
Contributor

IterWithTable seems to be the only way to marshal different tables into different types of structs. However how it is intended to be used is currently unclear to me. It seems that the pointer passed in will only be set / updated upon calling iter.Next however that creates a sort of catch 22.

You may not know what kind of object to pass into Next which will be used to decode dynamo result, but you need to call Next so you can figure out the table?

perhaps i am just missing something, but it seems that some more documentation on this code is likely needed since it's interface is a bit less intuitive.

@tamccall
Copy link
Contributor Author

tamccall commented Jul 17, 2024

As best i can tell you need to marshal into an intermediate value of a map[string]types.AttributeValue and then from there you can use the table pointer value to marshal that into a specific struct.

Maybe something like this?

var tablePointer string
var attributes map[string]types.AttributeValue
itr := batch.IterWithTable(&tablePointer)
for itr.Next(ctx, &attributes) {
	if tablePointer == "Foo" {
		//marshal into Table Foo
		var val Foo
		err := gDynamo.Unmarshal(&types.AttributeValueMemberM{Value: attributes}, &val)
		require.NoError(t, err)
	} else {
		// marshal into Table Bar
		var val Bar
		err := gDynamo.Unmarshal(&types.AttributeValueMemberM{Value: attributes}, &val)
		require.NoError(t, err)
	}
}

require.NoError(t, itr.Err())

like i said maybe an example in the godocs would be useful or potentially a testable example but that would probably be a bit more complicated to setup. You do seem to be using dynamo local though so idk if a testable example would be completely off the table. Might just need to setup more tables.

@guregu
Copy link
Owner

guregu commented Jul 19, 2024

Your example is the correct usage. I agree the interface kind of sucks, it was tacked on to the single-table version. More docs is always good, especially for confusing ones like this.
There is a fast path for decoding to map[string]types.AttributeValue at least.
Improving the multi-table batch is something I'd like to do soon. If you have any API ideas let me know and I'll consider it. One possibility is to make it more like the transaction API where you specify the output for each item. I could also see something like passing a map of table names to functions for decoding.

@guregu
Copy link
Owner

guregu commented Jul 19, 2024

Oh yeah, you can use dynamo.UnmarshalItem to avoid having to put it inside an M. This will use UnmarshalDynamoItem if it's defined as well.

@tamccall
Copy link
Contributor Author

tamccall commented Jul 19, 2024

If you have any API ideas let me know and I'll consider it.

One thing i was playing with was perhaps making a different iterator interface for this function

Perhaps somthing with this interface to seperate the "next check" from the record unmarshalling.

type WithTableIter interface {
	HasNext(ctx context.Context) bool
	Next(v any) error
	Err() error
}

Admittedly that is a bit clumsy as well bc clients will need to check the error twice but might be preferable to this tmp variable that is shown above.

@tamccall
Copy link
Contributor Author

I sent a pr for the godocs based on the current implementation. That should at least help until inspiration strikes for the batch get api.

@guregu
Copy link
Owner

guregu commented Jul 21, 2024

Thanks for the PR. With the new iterators coming in Go 1.23 (I think?) it's a good time to consider what the iterator API should become. I will think on it a bit.

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

No branches or pull requests

2 participants