-
-
Notifications
You must be signed in to change notification settings - Fork 94
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
implement meta id and timestamp logic #64
implement meta id and timestamp logic #64
Conversation
Codecov Report
@@ Coverage Diff @@
## main #64 +/- ##
==========================================
- Coverage 35.78% 34.20% -1.59%
==========================================
Files 28 28
Lines 1537 1725 +188
==========================================
+ Hits 550 590 +40
- Misses 930 1072 +142
- Partials 57 63 +6
Continue to review full report at Codecov.
|
Signed-off-by: Henry Jackson <34102861+henry-jackson@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
✅ This pull request was sent to the PullRequest network.
@henry-jackson you can click here to see the review status or cancel the code review job - or - cancel by adding [!pr] to the title of the pull request.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PullRequest Breakdown
Reviewable lines of change
+ 167
- 63
100% Go
Type of change
Feature - These changes are adding a new feature or improvement to existing code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Welcome to PullRequest! I added some comments regarding error handling and ways to possibly simplify your code.
Reviewers will be notified any time you reply to their comments or commit new changes.
You can also request a full follow-up review from your PullRequest dashboard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of great stuff here in this PR but I do suggest you make some changes.
Specifically, I called out where you need to use defer rows.Close()
to make sure you clean up the allocations that happen when you create a result.
I also suggest you look at the types you're using and either use int64
everywhere or use int
.
I also think you can use context.Background()
everywhere you're using context.TODO()
because you're never making calls to expire the context, you're not setting timeouts etc.
Additionally, I suggest the use of a logging package so that there's only one place in your entire application that cares about whether debugging is enabled. The package I suggested is used in thousands of applications and work very well.
Hopefully these suggestions are helpful. My goal is to try and save you from some very painful and weird debugging later!
Reviewers will be notified any time you reply to their comments or commit new changes.
You can also request a full follow-up review from your PullRequest dashboard.
|
||
timestamp := time.Now().Format(time.RFC3339) | ||
|
||
for key, value := range m { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's correct, we don't care about the order here!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
storage/postgres/aggregations.go
Outdated
sb := sqlbuilder.NewSelectBuilder() | ||
|
||
sb. | ||
Select("count(*)"). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to do count(*)
to get a row count on the table as this will have the database pull a lot of data. In fact, postgres does a full table scan to calculate this result. It would be better to just query for the highest value of the table since that can use an index or you should use a sequence to actually generate the IDs instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
implemented as selecting meta_id desc limit 1. Using a sequence to generate IDs seems like a great idea for a ticket! @altitude
storage/postgres/metadata.go
Outdated
|
||
if err != nil { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func (s *PGStore) FindMeta(q query.Query) (query.Cursor, error) { | ||
q.Limit = int(math.Max(-1, math.Min(float64(q.Limit), 100))) + 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ensures the limit value is between 0 and 101. The reason why, I'm not completely sure - it would be worth at least adding a comment to make this readable at a glance. This logic is borrowed from other FindX
functions such as FindTransaction. Checking git blame it looks like @altitude may have been the original author - Clem do you have any more info on the reason for this limit so that we could document?
storage/postgres/metadata.go
Outdated
return c, err | ||
} | ||
|
||
foundMetadata := map[int64]core.Metadata{} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is functionally identical. I'm going to leave this unchanged if this is just a style preference because this style matches all but one of the other empty map initializations in the repo
storage/postgres/metadata.go
Outdated
} | ||
|
||
results := make([]core.Metadata, len(foundMetadata)) | ||
for id, md := range foundMetadata { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
storage/postgres/metadata.go
Outdated
} | ||
c.Data = results | ||
|
||
total, _ := s.CountMeta() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
s refers to the *PGStore
in this function signature. Both the sqlite and postgres storage implementations have a CountMeta
function, and they each call their own implementation of CountMeta
.
What's confusing about the name to you? It is a requirement of implementations of interfaces that the methods have the same name as the interface, so CountMeta is pretty sensical to me as it describes what each database object will be doing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -35,6 +35,23 @@ func (s *SQLiteStore) CountAccounts() (int64, error) { | |||
return count, err | |||
} | |||
|
|||
func (s *SQLiteStore) CountMeta() (int64, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added more details and a re-written code segment to show a more efficient way to handle the list of data.
Reviewers will be notified any time you reply to their comments or commit new changes.
You can also request a full follow-up review from your PullRequest dashboard.
storage/postgres/metadata.go
Outdated
|
||
md := core.Metadata{} | ||
|
||
var ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I re-wrote this a bit to show a different way of doing it. This way you don't have to loop through all the data a second time.
foundMetadata := map[int64]core.Metadata{}
results := make([]core.Metadata, len(foundMetadata))
for rows.Next() {
md := core.Metadata{}
rows.Scan(
&md.metaID,
&md.targetType,
&md.targetID,
&md.metaValue,
)
var value json.RawMessage
err = json.Unmarshal([]byte(md), &value)
if err != nil {
return c, err
}
md.metaKey = value
foundMetadata[md.metaID] = md
results[md.metaID] = md
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There were some issues with this implementation:
- You initialize results with against the length of an empty map, so it is an empty array. This will always cause a panic when you do
results[md.metaID] = md
later. - Metadata does not have any of these fields you reference when scanning the row. The type is a wrapper around a
map[string]json.RawMessage
, that's why they are unmarshalled into standalone vars
Although, I do agree I can avoid iterating through my map and just initialize a slice that is of length q.Limit
. I initially implemented this and then decided to just remove this function from both storage implementations and the interface since I'm no longer using it to determine the last metadata id (originally I had been in order to follow the pattern set for finding the last transaction), and it seems out of scope to include in this PR without calling it in the business logic of the ledger
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I reviewed your feedback on my feedback. Much appreciated! My rewrite of the function wasn't meant to be production-grade. I had hoped only to illustrate some ways I've condensed those type of functions before.
Reviewers will be notified any time you reply to their comments or commit new changes.
You can also request a full follow-up review from your PullRequest dashboard.
Co-authored-by: Geoffrey Ragot <geoffrey.ragot@gmail.com> Co-authored-by: Maxence Maireaux <maxence@maireaux.fr>
Co-authored-by: Geoffrey Ragot <geoffrey.ragot@gmail.com> Co-authored-by: Maxence Maireaux <maxence@maireaux.fr>
Co-authored-by: Geoffrey Ragot <geoffrey.ragot@gmail.com> Co-authored-by: Maxence Maireaux <maxence@maireaux.fr>
Co-authored-by: Geoffrey Ragot <geoffrey.ragot@gmail.com> Co-authored-by: Maxence Maireaux <maxence@maireaux.fr>
closes #63
Can be tested by posting metadata to a transaction (using quickstart transaction data from README):
Checking db: