Comments (6)
Oh boy, this smells like Promises.
You should manually synchronize Permissions instead; there's always the option of manually checking if something is in the state.
from arikawa.
Oh boy, this smells like Promises.
What do you think will hinder this from working correctly?
You should manually synchronize Permissions instead; there's always the option of manually checking if something is in the state.
This, of course, is possible, this is rather for convenience and an attempt to save 12+ loc that have to be written instead of 1.
from arikawa.
What do you think will hinder this from working correctly?
Go's design is very anti-Promises, its entire point is to be explicit in asynchronicity. This means in a good API, the caller must have full control over that.
Not to mention, I personally hate to use Promises. It will really clutter up the API if we decide to do that.
from arikawa.
I think you misunderstood me. I didn't propose a system that returns a Promise
but, just one that internally will parallelize the execution of two possible API requests, reducing the wait time practically in half.
Example:
func (s *State) Permissions(channelID, userID discord.Snowflake) (discord.Permissions, error) {
if s.FetchSync {
return s.permissionsSync(channelID, userID)
}
return s.permissionsAsync(channelID, userID)
}
func (s *State) permissionsSync(channelID, userID discord.Snowflake) (discord.Permissions, error) {
ch, err := s.Channel(channelID)
if err != nil {
return 0, errors.Wrap(err, "Failed to get channel")
}
g, err := s.Guild(ch.GuildID)
if err != nil {
return 0, errors.Wrap(err, "failed to get guild")
}
m, err := s.Member(ch.GuildID, userID)
if err != nil {
return 0, errors.Wrap(err, "failed to get member")
}
return discord.CalcOverwrites(*g, *ch, *m), nil
}
func (s *State) permissionsAsync(
channelID, userID discord.Snowflake) (discord.Permissions, error) {
ch, err := s.Channel(channelID)
if err != nil {
return 0, errors.Wrap(err, "Failed to get channel")
}
guild, guildErr := make(chan *discord.Guild), make(chan error)
member, memberErr := make(chan *discord.Member), make(chan error)
go func() {
g, err := s.Guild(ch.GuildID)
if err != nil {
err = errors.Wrap(err, "failed to get guild")
}
guild <- g
guildErr <- err
}()
go func() {
m, err := s.Member(ch.GuildID, userID)
if err != nil {
err = errors.Wrap(err, "failed to get member")
}
member <- m
memberErr <- err
}()
g, err := <-guild, <-guildErr
if err != nil {
return 0, err
}
m, err := <-member, <-memberErr
if err != nil {
return 0, err
}
return discord.CalcOverwrites(*g, *ch, *m), nil
}
from arikawa.
This works, but 2 changes need to be done:
- This should check for a state first before asynchronously requesting. Goroutines are cheap, but not free.
- Given the above, Permissions could always call it asynchronously.
from arikawa.
This should do:
func (s *State) Permissions(channelID, userID discord.Snowflake) (discord.Permissions, error) {
ch, err := s.Channel(channelID)
if err != nil {
return 0, errors.Wrap(err, "Failed to get channel")
}
var wg sync.WaitGroup
g, guilderr := s.Store.Guild(ch.GuildID)
if guilderr != nil {
wg.Add(1)
go func() {
g, guilderr = s.Session.Guild(ch.GuildID)
wg.Done()
}()
}
m, membererr := s.Store.Member(ch.GuildID, userID)
if membererr != nil {
wg.Add(1)
go func() {
m, membererr = s.Store.Member(ch.GuildID, userID)
wg.Done()
}()
}
wg.Wait()
if guilderr != nil {
return 0, errors.Wrap(guilderr, "failed to get guild")
}
if membererr != nil {
return 0, errors.Wrap(membererr, "failed to get member")
}
return discord.CalcOverwrites(*g, *ch, *m), nil
}
from arikawa.
Related Issues (20)
- `gateway.Gateway.Latency()` appears to be broken HOT 1
- voice: Upstream breaking changes
- v3: cmdroute: Add Router.Group() HOT 2
- SelectComponent should be StringSelectComponent? HOT 1
- Description for StringSelectComponent is incorrect
- Could not find Message Content Intent HOT 1
- v3: Fix regression from c07f574
- Discord doesn't display command results SOLVED HOT 1
- Default avatar is calculated incorrectly for migrated accounts
- v4: Generate API and Gateway structures
- v4: Automatically emit Gateway commands for State wrappers
- v4: Return api.InteractionResponse for CommandHandler
- v4: ComponentHandler should allow type-constructing handlers
- Unable to instrument API call HOT 10
- Support for api/v9/guilds/<guildid>/members/supplemental
- feat: Spacebar support
- v3: Inconsistent channel permission values for large guilds between sessions HOT 9
- v3: Add cmdroute.Router.Group
- v3: CommandInteraction Doesn't Support Attachment Options
- Groups do not use autocompleter
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from arikawa.