-
Notifications
You must be signed in to change notification settings - Fork 618
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
Persistent message map #1996
base: master
Are you sure you want to change the base?
Persistent message map #1996
Conversation
c0f5d0c
to
890967e
Compare
@42wim With all the open PRs I have the branches are starting to get messy, can we start to get some of the PRs merged? (Whenever you're available) |
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.
The PR diff size of 22952 lines exceeds the maximum allowed for the inline comments feature.
890967e
to
c0f5d0c
Compare
gateway/gateway.go
Outdated
@@ -59,12 +63,41 @@ func New(rootLogger *logrus.Logger, cfg *config.Gateway, r *Router) *Gateway { | |||
if err := gw.AddConfig(cfg); err != nil { | |||
logger.Errorf("Failed to add configuration to gateway: %#v", err) | |||
} | |||
|
|||
persistentMessageStorePath, usePersistent := gw.Config.GetString("PersistentMessageStorePath") |
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.
Am I getting the config correctly here?
Unless I set it at the very top outside of any nesting it doesn't seem to work.
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.
@yousefmansy1 I'm merging them, thanks for your work on those PRs and sorry for the delays.
Thanks @42wim!
No worries at all, I'm sure you had a busy schedule.
As for how we're using getting config values, I have to put this value at a top level or else value comes back as nil
when I call gw.Config.GetString("PersistentMessageStorePath")
eg:
PersistentMessageStorePath="/etc/matterbridge/badger"
[discord]
[discord.bot]
...
[telegram]
[telegram.bot]
...
[whatsapp]
[whatsapp.googlevoice1]
...
[general]
...
Given this is a gateway level config value it should be under [general]
or any of the other gateway configs.
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.
You should use gw.BridgeValues().General.PersistentMessageStorePath
and add the setting to General
in bridge/config/config.go
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.
Resolved in 60219a3
Let me know if you hate the formatting applied in config, and I can undo.
@yousefmansy1 I'm merging them, thanks for your work on those PRs and sorry for the delays. |
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.
Haven't tested it yet, just quick review with some remarks
|
||
logger *logrus.Entry | ||
} | ||
|
||
type BrMsgID struct { | ||
br *bridge.Bridge | ||
ID string | ||
Protocol string |
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.
why removing the br
?
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.
We are directly storing these values in our persistent store, storing a reference to br, would just be garbage data when we read it back.
Based on the current usage of br
for this struct we are only using it to get the protocol and destination gateway name.
matterbridge/gateway/gateway.go
Lines 267 to 269 in 8587fa8
if dest.Protocol == id.br.Protocol && dest.Name == id.br.Name && channel.ID == id.ChannelID { | |
return strings.Replace(id.ID, dest.Protocol+" ", "", 1) | |
} |
For this persistent feature we are removing this reference and storing the direct values.
Unfortunately, that does mean if you change the name of the gateway things will break.
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.
Sure, I understand not storing the br
reference it self, but you can still reference br.Protocol
and br.Name
instead of creating those 2 variables? Or am I missing something about this?
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.
For the in memory cache yes.
But for the persistent message map, if we restart the application all the memory references we have stored inside our value store will point whatever is the old br
reference, which would be different for each run of the application.
I could be misunderstanding something about how references work in golang, correct me if I'm wrong.
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.
if you actually store br
it's a reference, but br.Protocol
or br.Name
is a string
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.
Oh ok I see. Yes, that would make more sense and would make its functionality more clear.
Will update.
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.
Actually maybe I'm misunderstanding
type BrMsgID struct {
Protocol bridge.Bridge.Protocol
DestName bridge.Bridge.Name
ChannelID string
ID string
}
causes build errors:
yousef@DESKTOP-YOUSEF $ go build -tags whatsappmulti -gcflags=all="-N -l"
# github.com/42wim/matterbridge/gateway
gateway/gateway.go:40:25: syntax error: unexpected . in struct type; possibly missing semicolon or newline or }
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.
BrMsgID stays the same with br *bridge.Bridge, where you need the protocol just use br.Protocol
I'm doing this on mobile so I could also be misunderstanding your issue
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 might also be misunderstanding what you mean, but this change is most important in this code snippet
When we get the []BrMsgID
from the message store, anything that we read from those items cant come from any reference.
gateway/gateway.go
Outdated
@@ -59,12 +63,41 @@ func New(rootLogger *logrus.Logger, cfg *config.Gateway, r *Router) *Gateway { | |||
if err := gw.AddConfig(cfg); err != nil { | |||
logger.Errorf("Failed to add configuration to gateway: %#v", err) | |||
} | |||
|
|||
persistentMessageStorePath, usePersistent := gw.Config.GetString("PersistentMessageStorePath") |
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.
You should use gw.BridgeValues().General.PersistentMessageStorePath
and add the setting to General
in bridge/config/config.go
gw.logger.Error(err) | ||
} | ||
|
||
if found { |
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.
return early
if found { | |
if !found { | |
return "" | |
} |
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 feel like that early return is less or at best equivalently inuitive.
The new code would probably loook like:
if ! found {
return ""
}
for _, id := range *destMessageIds {
// check protocol, bridge name and channelname
// for people that reuse the same bridge multiple times. see #342
if dest.Protocol == id.Protocol && dest.Name == id.DestName && channel.ID == id.ChannelID {
return id.ID
}
}
return ""
not really an improvement IMHO.
@@ -29,14 +30,17 @@ type Gateway struct { | |||
Message chan config.Message | |||
Name string | |||
Messages *lru.Cache | |||
MessageStore gokv.Store | |||
CanonicalStore gokv.Store |
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.
Is there a reason it can't be in 1 file?
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.
Yes, in order to add this feature without significant refactor we are still following the whole concept of a "canonical" message.
We need two separate mappings one for message->canonical (CanonicalStore
) and another for canonical->message[] (MessageStore
)
This is all highly related to this another PR:
#1991 (comment)
#1991 (comment)
On the file system the directories look like this:
Each bridge gets its own subdirectory
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.
Sure, but it's a k/v store, why can't you just put it in 1 file and use a "canonical" and "messages" prefix for the keys?
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 mean we can I suppose, I don't really see how that's beneficial.
I feel the code is more readable to have distinct mappings for their functionality?
Plus, removes the risk of breaking old message stores by needing to change a hypothetical prefix.
What do you think?
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.
seems like I didn't see that you said a subdirectory per bridge.
In my opinion it's much nicer to have everything in 1 file instead of a lot of files. So I'm even proposing to just have one database containing everything.
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.
Particularly for the subdirectories per bridge, I prefer that solution as its more flexible.
Flexible in the manner, that each folder is as if its its own table.
If a user needs to rename a bridge and don't want to lose their historical data they can just rename the directory.
Additionally Badger db does not support buckets/tables for each keystore so sub directories is really the only way to do it.
for example what I did in another PR with bbolt:
https://github.com/yousefmansy1/matterbridge/blob/5353b32c1a21d2655f8e12e76f81628373acd6f5/gateway/persistent.go#L21-L34
The way I'd like to treat it closer to a set of tables in a DB rather than one big KV store where we dump things in and "filter" with prefixes.
For the non technical user they can just treat the root directory as the whole db and ignore it.
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.
By the way unless we're always closing and opening the DB/KV handler with each Read/Write we do need individual stores for each one as each KV store actually holds a lock over the store. No other stores will be able to open it until it closes it's connection.
Its probably a little stupid but we'll never run into this blocking if each gateway has its own store it keeps for itself.
(also reformatted and sorted the config struct)
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.
The PR diff size of 23162 lines exceeds the maximum allowed for the inline comments feature.
Code Climate has analyzed commit 60219a3 and detected 0 issues on this pull request. View more on Code Climate. |
@42wim could you return back here, please (: |
@42wim any news with PR review? |
@42wim ? |
Persistent message map
Resolves #541