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

feat(community)_: add version to image url to let clients update #6118

Open
wants to merge 1 commit into
base: refactor/dont-use-cache-for-image-server
Choose a base branch
from

Conversation

jrainville
Copy link
Member

Fixes status-im/status-desktop#16688

Since we use the local image server to show the community image, the URL never changes when we update the image, since it's served using a query string containing the community ID. eg: https://Localhost:46739/communityDescriptionImages?communityID=0x03c5ece7da362d31199fb02d632f85fdf853af57d89c3204b4d1e90c6ec13bb23c&name=thumbnail Because of that, the clients cannot know if the image was updated, so they had to force update the image every time, which was inefficient.

We discovered this issue when I refactored the community client code in Desktop so that we only update the changed properties of a community instead of reseting the whole thing.

The solution I came up with in the PR is to add a version to the URL when we detect that the image changed. This let,s the clients detect when the image was updated without having to do any extra logic.

@status-im-auto
Copy link
Member

status-im-auto commented Nov 22, 2024

Jenkins Builds

Click to see older builds (39)
Commit #️⃣ Finished (UTC) Duration Platform Result
✔️ dfc4dc8 #1 2024-11-22 20:06:26 ~4 min macos 📦zip
✔️ dfc4dc8 #1 2024-11-22 20:06:49 ~5 min ios 📦zip
✖️ dfc4dc8 #1 2024-11-22 20:06:50 ~4 min tests-rpc 📄log
✔️ dfc4dc8 #1 2024-11-22 20:06:56 ~5 min linux 📦zip
✔️ dfc4dc8 #1 2024-11-22 20:07:52 ~6 min android 📦aar
✔️ dfc4dc8 #1 2024-11-22 20:08:00 ~6 min windows 📦zip
✔️ dfc4dc8 #1 2024-11-22 20:09:07 ~7 min macos 📦zip
✖️ dfc4dc8 #1 2024-11-22 20:35:24 ~33 min tests 📄log
✖️ 65d153d #2 2024-11-26 19:29:43 ~3 min tests-rpc 📄log
✔️ 65d153d #2 2024-11-26 19:30:46 ~4 min windows 📦zip
✔️ 65d153d #2 2024-11-26 19:30:57 ~5 min linux 📦zip
✔️ 65d153d #2 2024-11-26 19:31:01 ~5 min macos 📦zip
✔️ 65d153d #2 2024-11-26 19:31:07 ~5 min ios 📦zip
✔️ 65d153d #2 2024-11-26 19:31:51 ~6 min android 📦aar
✔️ 65d153d #2 2024-11-26 19:33:19 ~7 min macos 📦zip
✖️ 65d153d #3 2024-11-26 19:33:32 ~3 min tests-rpc 📄log
✔️ 65d153d #3 2024-11-26 19:35:49 ~4 min linux 📦zip
✔️ 65d153d #3 2024-11-26 19:36:13 ~5 min macos 📦zip
✔️ 65d153d #3 2024-11-26 19:36:42 ~5 min ios 📦zip
✖️ 65d153d #2 2024-11-26 19:37:37 ~11 min tests 📄log
✔️ 65d153d #3 2024-11-26 19:37:58 ~6 min android 📦aar
✔️ 65d153d #3 2024-11-26 19:40:50 ~7 min macos 📦zip
✖️ 65d153d #3 2024-11-26 19:47:38 ~9 min tests 📄log
✖️ 64d4e66 #4 2024-11-26 21:34:01 ~3 min tests-rpc 📄log
✖️ 64d4e66 #4 2024-11-26 21:34:20 ~3 min tests 📄log
✔️ 64d4e66 #3 2024-11-26 21:35:14 ~4 min windows 📦zip
✔️ 64d4e66 #4 2024-11-26 21:35:23 ~5 min linux 📦zip
✔️ 64d4e66 #4 2024-11-26 21:35:26 ~5 min macos 📦zip
✔️ 64d4e66 #4 2024-11-26 21:35:34 ~5 min ios 📦zip
✔️ 64d4e66 #4 2024-11-26 21:36:23 ~6 min android 📦aar
✔️ 64d4e66 #4 2024-11-26 21:38:53 ~8 min macos 📦zip
✖️ 16a9843 #5 2024-11-26 21:37:52 ~3 min tests-rpc 📄log
✔️ 16a9843 #4 2024-11-26 21:39:19 ~4 min windows 📦zip
✔️ 16a9843 #5 2024-11-26 21:40:31 ~5 min macos 📦zip
✔️ 16a9843 #5 2024-11-26 21:40:40 ~5 min linux 📦zip
✔️ 16a9843 #5 2024-11-26 21:41:03 ~5 min ios 📦zip
✔️ 16a9843 #5 2024-11-26 21:42:42 ~6 min android 📦aar
✖️ 16a9843 #5 2024-11-26 21:44:48 ~10 min tests 📄log
✔️ 16a9843 #5 2024-11-26 21:46:34 ~7 min macos 📦zip
Commit #️⃣ Finished (UTC) Duration Platform Result
✖️ b8d2544 #6 2024-11-27 15:10:19 ~4 min tests-rpc 📄log
✔️ b8d2544 #5 2024-11-27 15:10:28 ~4 min windows 📦zip
✔️ b8d2544 #6 2024-11-27 15:11:52 ~5 min linux 📦zip
✔️ b8d2544 #6 2024-11-27 15:12:13 ~6 min android 📦aar
✔️ b8d2544 #6 2024-11-27 15:12:53 ~6 min ios 📦zip
✔️ b8d2544 #6 2024-11-27 15:12:58 ~6 min macos 📦zip
✔️ b8d2544 #6 2024-11-27 15:13:37 ~7 min macos 📦zip
✖️ b8d2544 #6 2024-11-27 15:16:52 ~10 min tests 📄log
✔️ b3659a1 #6 2024-11-27 15:58:18 ~4 min windows 📦zip
✔️ b3659a1 #7 2024-11-27 15:59:37 ~5 min tests-rpc 📄log
✔️ b3659a1 #7 2024-11-27 15:59:48 ~5 min macos 📦zip
✔️ b3659a1 #7 2024-11-27 15:59:49 ~5 min linux 📦zip
✔️ b3659a1 #7 2024-11-27 15:59:58 ~6 min ios 📦zip
✔️ b3659a1 #7 2024-11-27 16:00:18 ~6 min android 📦aar
✔️ b3659a1 #7 2024-11-27 16:02:16 ~8 min macos 📦zip
✖️ b3659a1 #7 2024-11-27 16:23:18 ~29 min tests 📄log

for imageType, newImage := range description.Identity.Images {
oldImage, ok := o.config.CommunityDescription.Identity.Images[imageType]
if ok {
// FIXME this does not work!!!!!
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe a leftover comment?

Copy link
Member

@caybro caybro left a comment

Choose a reason for hiding this comment

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

LGTM

u := s.MakeBaseURL()
u.Path = communityDescriptionImagesPath
u.RawQuery = url.Values{
"communityID": {communityID},
"name": {name},
"version": {strconv.FormatUint(uint64(version), 10)},
Copy link
Member

Choose a reason for hiding this comment

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

uint64 here and uint32 everywhere else?

Copy link
Member Author

Choose a reason for hiding this comment

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

FormatUint accepts uint64 only 🤷

Copy link
Member

Choose a reason for hiding this comment

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

🙄 go doesn't have some sort of generics or method overloads? 😮

@@ -58,6 +58,10 @@ message IdentityImage {
// encrypted signals the encryption state of the payload, default is false.
bool encrypted = 5;

// version iterator of the image since images use a localUrl to be shown,
// this iterator makes sure the image URL changes when a new image is given
uint32 version = 6;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Wait, so version is not just local, it becomes part of CommunityDescription? 🤔
Sounds a bit weird to be like that, like this problem should be solved solely on client side, not affecting network messages

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah I agree it should be local only, but I didn't find an easy way to do so, since locally, we use the IdentityImage protobuf in the image server.

I'm very open for suggestions to make it locally, but apart from creating some sort of new column or table, I don't know how to make it work.

In the end, this solution is pretty unobtrusive anyway IMO.

Copy link
Collaborator

@igor-sirotin igor-sirotin Nov 25, 2024

Choose a reason for hiding this comment

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

@jrainville I think I'm not convinced, modifying protocol for local needs sounds counter-intuitive to me.

We should probably wrap the IdentityImage when passing it to ServerMedia, and add the Version property to the wrapper. Dunno, or make some method of the media server to update the version of specific image.

creating some sort of new column or table

We don't need to persist the version, it's enough to have it only during a single run. After restart, version can go again from 1, should work, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

We don't need to persist the version, it's enough to have it only during a single run. After restart, version can go again from 1, should work, right?

That's true. I'll try to see if I can do as you say

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with Igor here.

At first glance, the best would be to use/extend CommunityChanges with image change recognition and then populate it to client.

Copy link
Member Author

Choose a reason for hiding this comment

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

We don't need to persist the version, it's enough to have it only during a single run. After restart, version can go again from 1, should work, right?

Ok, I tried something simple and I realized that we indeed need to save it somewhere. At least a local cache. However, we do not have a local cache for communities. The closest we have is the encrypted_community_description_cache which is a table. It is also what the image server uses to serve the images.

Just to make sure the problem is clear, I can't just pass the updated version to the image server, since the Edit happens in one thread/timeframe and the image serving is a completely different one, so the image server knows nothing about image updates.
It serves using the community cache table, which is populated from the decrypted community description. So we need the version or at least an indicator that the images were updated in there.

So either I create a new local cache for image versions per community, or I add a new column encrypted_community_description_cache to save the version, or leave it as I did it. Or you guys have a better option?

Copy link
Contributor

@osmaczko osmaczko left a comment

Choose a reason for hiding this comment

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

Sorry, I need to request changes for this one.

protocol/communities/manager.go Outdated Show resolved Hide resolved
@@ -58,6 +58,10 @@ message IdentityImage {
// encrypted signals the encryption state of the payload, default is false.
bool encrypted = 5;

// version iterator of the image since images use a localUrl to be shown,
// this iterator makes sure the image URL changes when a new image is given
uint32 version = 6;
Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with Igor here.

At first glance, the best would be to use/extend CommunityChanges with image change recognition and then populate it to client.

@jrainville jrainville force-pushed the fix/community-image-not-updating branch from dfc4dc8 to 65d153d Compare November 26, 2024 19:25
@jrainville jrainville changed the base branch from develop to refactor/dont-use-cache-for-image-server November 26, 2024 19:25
@jrainville
Copy link
Member Author

@igor-sirotin @osmaczko I rebased this branch on top of #6127 as I refactored the media sever to not use the community cache.
So I don't need preprocessDescription anymore 🙌

As for the version being in the protobuf, I sadly didn't find a good solution. I'm still hoping you guys can think of something 😕

@jrainville
Copy link
Member Author

Patryk gave me a good suggestion:

or another trick to do in manager.go:
mediaServer.ImageVersion(func(communityID string) { return imageVersions[communiyID]})

And in UpdateImageVersions you update the imageVersions map instead ChatIdentity
This way clients would work fine without changes

Using a local map in the manager

Copy link

codecov bot commented Nov 26, 2024

Codecov Report

Attention: Patch coverage is 0% with 14 lines in your changes missing coverage. Please review.

Project coverage is 0.00%. Comparing base (d197857) to head (65d153d).

Files with missing lines Patch % Lines
protocol/communities/community.go 0.00% 10 Missing ⚠️
protocol/communities/manager.go 0.00% 2 Missing ⚠️
server/server_media.go 0.00% 2 Missing ⚠️
Additional details and impacted files
@@                            Coverage Diff                            @@
##           refactor/dont-use-cache-for-image-server    #6118   +/-   ##
=========================================================================
  Coverage                                      0.00%    0.00%           
=========================================================================
  Files                                           811      811           
  Lines                                        108069   108080   +11     
=========================================================================
- Misses                                       108069   108080   +11     
Flag Coverage Δ
functional 0.00% <0.00%> (ø)

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

Files with missing lines Coverage Δ
protocol/communities/manager.go 0.00% <0.00%> (ø)
server/server_media.go 0.00% <0.00%> (ø)
protocol/communities/community.go 0.00% <0.00%> (ø)

@jrainville jrainville force-pushed the fix/community-image-not-updating branch 2 times, most recently from 64d4e66 to 16a9843 Compare November 26, 2024 21:31
@jrainville
Copy link
Member Author

I updated the PR to go with Patryk's recommendation. I no longer need the protobuf changes and the version isn't saved anymore. Please let me know what you think 😄

@jrainville jrainville force-pushed the refactor/dont-use-cache-for-image-server branch from d197857 to 064d880 Compare November 27, 2024 14:54
@jrainville jrainville force-pushed the fix/community-image-not-updating branch from 16a9843 to b8d2544 Compare November 27, 2024 15:05
@jrainville jrainville force-pushed the refactor/dont-use-cache-for-image-server branch from 064d880 to bc4b467 Compare November 27, 2024 15:51
Fixes status-im/status-desktop#16688

Since we use the local image server to show the community image, the URL never changes when we update the image, since it's served using a query string containing the community ID. eg: `https://Localhost:46739/communityDescriptionImages?communityID=0x03c5ece7da362d31199fb02d632f85fdf853af57d89c3204b4d1e90c6ec13bb23c&name=thumbnail`
Because of that, the clients cannot know if the image was updated, so they had to force update the image every time, which was inefficient.

We discovered this issue when I refactored the community client code in Desktop so that we only update the changed properties of a community instead of reseting the whole thing.

The solution I came up with in the PR is to add a `version` to the URL when we detect that the image changed. This let's the clients detect when the image was updated without having to do any extra logic.
@jrainville jrainville force-pushed the fix/community-image-not-updating branch from b8d2544 to b3659a1 Compare November 27, 2024 15:53
Comment on lines +485 to +489
version, ok := manager.communityImageVersions[communityID]
if !ok {
return 0
}
return version
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
version, ok := manager.communityImageVersions[communityID]
if !ok {
return 0
}
return version
return manager.communityImageVersions[communityID]

@@ -1616,6 +1625,15 @@ func (m *Manager) UpdatePubsubTopicPrivateKey(topic string, privKey *ecdsa.Priva
return m.transport.RemovePubsubTopicKey(topic)
}

func (m *Manager) incrementCommunityImageVersion(communityID string) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Would be great to add a comment explaining why this is needed.

@@ -243,6 +255,7 @@ func (s *MediaServer) MakeCommunityImageURL(communityID, name string) string {
u.RawQuery = url.Values{
"communityID": {communityID},
"name": {name},
"version": {strconv.FormatUint(uint64(s.getCommunityImageVersion(communityID)), 10)},
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
"version": {strconv.FormatUint(uint64(s.getCommunityImageVersion(communityID)), 10)},
"version": {fmt.Sprintf("%d", s.getCommunityImageVersion(communityID))},

Comment on lines +1629 to +1634
version, ok := m.communityImageVersions[communityID]
if !ok {
// First time the image is updated, so update the version to 1 (it was 0 by default)
m.communityImageVersions[communityID] = 1
}
m.communityImageVersions[communityID] = version + 1
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
version, ok := m.communityImageVersions[communityID]
if !ok {
// First time the image is updated, so update the version to 1 (it was 0 by default)
m.communityImageVersions[communityID] = 1
}
m.communityImageVersions[communityID] = version + 1
m.communityImageVersions[communityID] = m.communityImageVersions[communityID] + 1

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.

[Community] Changing logo doesn't get propagated
7 participants