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

Use voting_method for voting, delegations & results #227

Merged
merged 61 commits into from
Apr 13, 2021

Conversation

jinjagit
Copy link
Member

@jinjagit jinjagit commented Mar 31, 2021

Aim: To pass voting_method via absinthe/GraphQl, and when it is included, record and use its value appropriately.

Addresses #225

Add to liquid_voting_web/schema.
Now can be passed in via GraphQl.
@jinjagit jinjagit marked this pull request as draft March 31, 2021 10:18
@jinjagit jinjagit self-assigned this Mar 31, 2021
Previous unique index would have prevented participant having two
or more votes with different voting methods for same proposal.
Also fix typo in voting_methods test module name.
1 test failing - expected - as not yet including voting_method
upsert in vote creation. Expect more to fail as dev continues,
before finally fixing to reflect new methodology.
@jinjagit
Copy link
Member Author

1 test failing - expected - as not yet including voting_method upsert in vote creation. Expect more to fail as dev continues, before finally fixing to reflect new methodology.

@jinjagit jinjagit changed the title Use voting_method for voting, Use voting_method for voting Mar 31, 2021
Creates voting_method record and association with vote.
All kinds of voting related tests now breaking, as expected.
This disambiguates the field from the model/struct, and results in
a selector: `voting_method.name`, rather than the confusing
`voting_method.voting_method`.
This makes core voting tests pass, but core voting functions
mostly do not yet make appropriet use of voting_method.

Also rename absinthe schema field to match model field name.
Also edit vote and voting_method factories to use new model
field name.
Also edit get_vote!/2 to include |> Repo.preload([:voting_method]).
Also edit test of get_vote!/2 to take advantage of preload.
Also add VotingMethods as Dataloader source in absinthe schema.
Also add voting_method field to vote object in absinthe schema.

These changes mean we can now return the values of associated
voting_method fields in a votingMethod subgroup, when returning a
query of a / some Vote(s).
Use Mutli.run in lib/liquid_voting_web/resolvers/voting.ex
create_vote/3 funtion.
Error handling may not yet cover all possible error matching.
Also remove all_fields var where is equivalent to required_fields.
Also add error field :action to help user understand which, of 3,
actions involved in create_vote (upsert voting_method,
upsert_participant, create_vote) gave rise to the error.
Merges in removal of unused vars in delegations test.
Also add :voting_method to telemetry :params in create_vote/1
All tests should be green at this point.
@jinjagit
Copy link
Member Author

jinjagit commented Apr 1, 2021

Summary of progress:

  • All tests currently green, though I expect to add more specific tests as work continues / when work is nearing completion.
  • Creation of vote now requires a voting_method parameter (at core and absinthe layers), which equates to voting_method.name.
  • votingMethod (and its fields and values) now exposed as associated with any existing vote(s) at absinthe layer = can be queried in query of vote(s)
  • results calculation does not yet involve voting_method
  • list_votes does not yet make use of voting_method

@oliverbarnes @davefrey This feels like a good point to get some feedback / ask & answer questions. I could participate in a meeting about this, if preferred.

Unfortunately, I cannot submit for review as merging this will break our Decidim demo, and I can't really fix that until the api is ready to work fully in voting_method mode.

@davefrey
Copy link
Member

davefrey commented Apr 1, 2021

Hi Simon, congrats!

I can definitely review in the morning...I won't have the time to look carefully today.

You might describe more your approach and decisions in the PR description, that way I can understand your intent rather than inferring from the code: it will help me separate what you wanted to do from whether the code matches.

For example my first questions...again I can infer from the code, but tell us the story :-)

  • is this voting method required or do we have a default on the api (does the client have to send one)
  • is the voting result that we return for (almost) all mutators meant to include a count just for that voting method (just the supports count for example), or a comprehensive result for the proposal url (counts for endorsements and supports)?

Apologies if this is all laid out in previous slack or git issue conversations, ideally I'd be current on all that. And if your implementation intention is set out in the issue that's 👍 for me...closely reading the issue is part of PR review, and I'll get there.

@jinjagit
Copy link
Member Author

jinjagit commented Apr 1, 2021

@davefrey Thanks for the feedback! Here's some answers to your questions + some additional info:

* is this voting method required or do we have a default on the api (does the client have to send one)
  • Required when creating a vote. In discussion with Oliver, we decided this was the easiest way to avoid the complexities of trying to create a unique index against possible null values (do-able, but then creates Postgrex exception, which would need special handling, if an empty string is given for voting_method.name) & to also avoid explicitly setting a default string value. This means a voting_method is required even when a voting context (e.g. proposal_url) only has one 'method'.
  • Is associated with a result, and will be required when initiating a result calculation (not yet implemented).
  • May be required for list_votes, though I am currently undecided on this, as I can see pros and cons in having both a list_all_votes (of all voting methods) and a list_votes_for_voting method action.
* is the voting result that we return for (almost) all mutators meant to include a count just for that voting method (just the supports count for example), or a comprehensive result for the proposal url (counts for endorsements and supports)?
  • Voting results will be specific to a voting_method (and proposal_url).

Additional information:

The fundamental change is the creation of a VotingMethods table, for VotingMethod structs, with the fields :uuid and :name (string).

  • The VotingMethod struct is associated with each Vote, and will be associated with each Result.
  • These associations are / will be established by use of the core upsert_voting_method/1 function, called by the appropriate absinthe mutation paths (e.g. currently, it is added to the createVote path(s)).
  • These associations are / will also be used in the appropriate absinthe query paths (e.g. currently, it is used by the Vote query path).

@oliverbarnes
Copy link
Member

This is looking good 🚀 I'll review again once the voting result part is done.

Good point about this only being mergeable when another PR on the module side consuming the new field is ready as well, we'll need to merge them both in tandem.

The only thing here that got me scratching my head so far is the updated index - I'm wondering if it's too granular. They have a cost in write time the bigger they get, and sometimes that outweighs the benefit.

But I honestly need to refresh up on this topic, so I can't say for sure. This is good homework for you, @jinjagit: reading up on composite index best practices and give us a tldr on current state of our indexing, and then revisit the indexing change in this PR in light of what you find

@jinjagit
Copy link
Member Author

jinjagit commented Apr 1, 2021

@oliverbarnes updated index - I'm wondering if it's too granular. They have a cost in write time the bigger they get, and sometimes that outweighs the benefit.

Thanks for the input. I'll look into it now.

Add voting_method(name) field to asbinthe deleteDelegation
mutation, in schema and delete_delegation resolver function.
Update doc comments for delete/delegation/5 core function.
Also remove debug output from existing_delegations_test.exs
proposalUrl and votingMethods fields are optional, but
providing only a voting method, without a proposal url, will
result in an error explaining that a proposal url is
required IF a voting method is specified.
If a proposal url is specified, with no voting method, then
votes for the proposal url and voting method with name
"default" will be returned.
Providing neither will return all votes for an organization.
An empty list is returned if no matching result(s) found.
New file: test/liquid_voting_web/absinthe/queries/votes_test.exs.
Also remove unused vars and comments.
@jinjagit
Copy link
Member Author

jinjagit commented Apr 8, 2021

Note: Because we decided to use a default value for votingMethod :name, all the examples in the readme still work without any need to edit them 👍

@jinjagit jinjagit changed the title Use voting_method for voting Use voting_method for voting, delegations & results Apr 10, 2021
@jinjagit
Copy link
Member Author

jinjagit commented Apr 12, 2021

Video summary on YouTube
Video with transcript on Descript

@oliverbarnes @davefrey Hopefully, the video will help give an overview.

@jinjagit jinjagit marked this pull request as ready for review April 12, 2021 22:11
@jinjagit jinjagit marked this pull request as draft April 12, 2021 22:21
@jinjagit
Copy link
Member Author

jinjagit commented Apr 12, 2021

This should not break the demo if merged, since it will upsert votingMethod: "default" to our API database, for the current proposal support integration,and votingResults with no specified votingMethod should also return results for votingMethod: "default", without any need to edit the demo code and the graphQL mutations and queries it currently uses. 🤞

@jinjagit jinjagit marked this pull request as ready for review April 12, 2021 23:53
Copy link
Member

@oliverbarnes oliverbarnes left a comment

Choose a reason for hiding this comment

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

Thanks for all the work put into this, @jinjagit!

This is a big PR, but unavoidable due to the new voting_method being an almost global constraint, and much of the changes would break everything else if submitted separately.

Some of the api codebase was already due some refactoring and optimization, and some of the changes here increase that need a bit, but that tech debt is better tackled separately, in discrete and small PRs. They also take lower priority to moving ahead with integrating Decidim proposal endorsements, which depends on this PR.

I'm just going to note these small things here, for reference when tackling that:

  • Repo preloads can take collections of associations, so multiple calls to it can be merged into one
  • Some separate db queries might be more efficient if merged into a single one using joins
  • Some function signatures are getting pretty big
  • Some function are getting pretty complex, and this is already captured in some discussions here in the repo

And a subtle point: voting method sometimes comes as an argument in function signatures before proposal_url, when it's a constraint that most of the time will just use the default, and our domain it has a lower place - proposal, vote and delegation info pertain to the user actions (the user story), whereas voting method and organization id are more platform constraints - the user isn't choosing either in their voting and delegations, they're just given.

It's subtle but helps navigate the code if this hierarchy is clear and consistent :)

Going ahead and merging. Great work 👏

@oliverbarnes oliverbarnes merged commit 9aed184 into master Apr 13, 2021
@oliverbarnes oliverbarnes deleted the use-voting-method-for-voting branch April 13, 2021 11:07
@jinjagit
Copy link
Member Author

jinjagit commented Apr 13, 2021

@oliverbarnes Great feedback. Thanks! I'll create a/some issue(s) to cover the points you make.

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

Successfully merging this pull request may close these issues.

3 participants