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

fix(i): JSON object default value panic #3156

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

nasdf
Copy link
Member

@nasdf nasdf commented Oct 18, 2024

Relevant issue(s)

Resolves #3146

Description

This PR fixes an issue where JSON default values containing objects would cause a panic related to a map key hash. Moving the default value off of the FieldDefinition appears to fix the issue.

Tasks

  • I made sure the code is well commented, particularly hard-to-understand areas.
  • I made sure the repository-held documentation is changed accordingly.
  • I made sure the pull request title adheres to the conventional commit style (the subset used in the project can be found in tools/configs/chglog/config.yml).
  • I made sure to discuss its limitations such as threats to validity, vulnerability to mistake and misuse, robustness to invalidation of assumptions, resource requirements, ...

How has this been tested?

Updated integration tests

Specify the platform(s) on which this was tested:

  • MacOS

@nasdf nasdf added the bug Something isn't working label Oct 18, 2024
@nasdf nasdf added this to the DefraDB v0.14 milestone Oct 18, 2024
@nasdf nasdf self-assigned this Oct 18, 2024
@nasdf nasdf changed the title fix(i) JSON object default value panic fix(i): JSON object default value panic Oct 18, 2024
Copy link

codecov bot commented Oct 18, 2024

Codecov Report

Attention: Patch coverage is 94.73684% with 1 line in your changes missing coverage. Please review.

Project coverage is 78.14%. Comparing base (b268c0b) to head (b75cf79).

Files with missing lines Patch % Lines
internal/lens/fetcher.go 75.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop    #3156      +/-   ##
===========================================
+ Coverage    77.98%   78.14%   +0.15%     
===========================================
  Files          354      354              
  Lines        34669    34674       +5     
===========================================
+ Hits         27036    27093      +57     
+ Misses        6003     5966      -37     
+ Partials      1630     1615      -15     
Flag Coverage Δ
all-tests 78.14% <94.74%> (+0.15%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
client/definitions.go 76.24% <100.00%> (+0.60%) ⬆️
internal/db/fetcher/encoded_doc.go 73.63% <100.00%> (ø)
internal/db/fetcher/fetcher.go 78.55% <100.00%> (ø)
internal/db/fetcher/indexer.go 83.92% <100.00%> (ø)
internal/lens/fetcher.go 71.63% <75.00%> (+1.40%) ⬆️

... and 14 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b268c0b...b75cf79. Read the comment docs.

@nasdf nasdf force-pushed the nasdf/fix/json-default-value-panic branch from 2b8dceb to f42f255 Compare October 18, 2024 17:04
@nasdf nasdf force-pushed the nasdf/fix/json-default-value-panic branch from f42f255 to e0706db Compare October 18, 2024 20:36
Copy link
Collaborator

@fredcarle fredcarle left a comment

Choose a reason for hiding this comment

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

Context for other reviewers, the panic was caused by the fact that client.FieldDefinition is used as the key for a map of properties on encodedDocument. For a Go type to be used as a map key it has to be comparable. Within client.FieldDefinition, the DefaultField struct field is of type any and until we added support for JSON default, it only ever contained scalar types. But a default JSON value can be an object which is represented as a map[string]any. A map is not a comparable type and this was causing a runtime panic when trying to create a new doc using the default JSON object. This panic happened in the fetcher code github.com/sourcenetwork/defradb/internal/db/fetcher/fetcher.go:544 when fetching the new document within the creation request.

I'm OK with removing DefaultValue from client.FieldDefinition for now although a better fix might be to change the fetcher code. @AndrewSisley might have a stronger opinion for this one.

Copy link
Contributor

@AndrewSisley AndrewSisley left a comment

Choose a reason for hiding this comment

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

todo: I do not agree with removing it from here - this object is supposed to be a unified object containing the result of local+global configuration and taking it off this breaks that. It will result in weirdness for users (as well as internal code) where some public functions returning Definitions cannot inform users as to what the default value is.

I feel even more strongly about this given that it is described as a somewhat accidental result from the fix, that this just happened to be the quickest way to fix a bug and wasn't really a long term design choice.

Please either discuss the with the whole team over discord or in the standup.

Furthermore, going by:

the panic was caused by the fact that client.FieldDefinition is used as the key for a map of properties on encodedDocument.

The alternative looks pretty simple and non invasive/internal - just use the field ID or name as the map key - they are identifiers and using the whole object sounds unneeded and error prone anyway.

@nasdf nasdf requested a review from AndrewSisley October 23, 2024 15:49
@@ -68,8 +68,8 @@ type encodedDocument struct {
id []byte
schemaVersionID string
status client.DocumentStatus
properties map[client.FieldDefinition]*encProperty
decodedPropertyCache map[client.FieldDefinition]any
properties map[client.FieldDefinitionKey]*encProperty
Copy link
Contributor

Choose a reason for hiding this comment

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

question: Why are you using both field ID and Name here? At a single point in time either will be unique - you can't two fields with the same fieldID or with the same name.

Copy link
Member Author

Choose a reason for hiding this comment

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

Both the field ID and name are used in the downstream dependencies. If we used only one as the map key then we would need to expand the FieldDefinition API to support looking up a field by ID or copy paste a lookup function into a few places. I think having the FieldDefinitionKey is the better alternative.

Copy link
Contributor

@AndrewSisley AndrewSisley Oct 23, 2024

Choose a reason for hiding this comment

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

There should already be functions to get fields by Name if you use that as the key - I don't think you'd need to add anything to client.

Having a (public) FieldDefinitionKey struct with name and key properties suggests that they need to be combined in order to form a unique key - which is incorrect.

Copy link
Member Author

Choose a reason for hiding this comment

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

The DecodeToDoc function in the fetcher doesn't have a reference to the definition so it can't lookup the field ID from the name.

I'm fine with changing the struct name but I don't see any issues with the way I implemented it.

Copy link
Contributor

Choose a reason for hiding this comment

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

DecodeToDoc just uses the field ID as an index - we could change that too. Or you could change encodedDocument.properties to a slice containing field name and value.

There are many ways to solve this internal coding problem that don't involve changing the public types, especially not in a way that seems a little misleading.

@nasdf nasdf requested a review from AndrewSisley October 28, 2024 16:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

JSON object default value causes panic
3 participants