SyncServerII / Neebla

Private and Self-Owned Social Media
MIT License
1 stars 2 forks source link

Additional attributes per media item #15

Open crspybits opened 3 years ago

crspybits commented 3 years ago

I list several pieces of functionality below, because I think they naturally group together.

Cross-device unread counts Unread counts for specific media items/albums that can be shared with other devices for the specific user. Also so that if you have to re-install the app it preserves unread counts.

Keyword support for media It would be nice to have keywords per media item. Not sure if it should be a new file or part of the discussion. Definitely need some change to a change resolver. Keywords could be added or removed. But not changed specifically I think. Possibly single word keywords. Or “atomic” phrases that can’t be edited-- but can be removed and then added. Each user could change a keyword (e.g., remove one) that someone else added. These keywords are shared across users.

Marking media items with a limited set of visual icons aka Badges One per user. E.g., you could mark the media item with “Thumbs up”. Dany’s badge idea: Old vs. new testament.

My plan is to implement this as a single additional file per media item. Implemented as a JSON structure, this could look like the following for a specific media item:

{
    “unreadCounts”: {
        “userId1”: User1_Unread_Count,
        “userId2”: User2_Unread_Count,
        // etc.
    },

    “keywords”: {
                 “Keyword1”: true,
                 “Keyword2”: false,
                  etc.
        },

    “badges”: {
        “userId1”: badge1,
        “userId2”: badge2,
        // etc.
    }
}

There are a couple of technical challenges with this change:

1) How do we do conflict resolution on these files?

2) How can a client app know when a specific change to one of these files should be indicated as "downloadable" in the album list for the Neebla app?

I address these below.

crspybits commented 3 years ago

Conflict resolution:

1) unreadCounts: the maximum of two (same) userId keys could be used. I.e., the maximum across the current and last value for the same UserId.

2) keywords: I’m indicating that the value of this be stored as a dictionary rather than an array to make it easier to detect removals. I’d never remove an entry from this array, just switch between true and false. Conflict resolution would just be to take the last set value for a specific keyword as the winner. Keywords marked as “false” would not actually be shown to the user. The keys would not be some full set of keys, but rather just the full set added by any user to the keywords.

3) Badges: A change will just overwrite the prior change for a specific user id. The last change in wins.

crspybits commented 3 years ago

How can a client app know when a specific change to one of these files should be indicated as "downloadable" in the album list for the Neebla app?

unreadCounts: Each change applies to just a single userId-- i.e., for a single user. And as I’m conceiving the UI currently, other users wouldn’t know about the unreadCount for self. And self doesn’t need to have the UI marked as downloadable in the album-- rather self just needs the unreadCount updated on a specific item. Conclusion: Somehow need to have changes like this not be marked as downloadable in the album, across any users.

Keywords: Other users should have this update marked as downloadable in the album, but not self. Self already knows about the change. Other users don’t yet know about the change.

Badges: Other users should have this update marked as downloadable in the album, but not self. Self already knows about the change. Other users don’t yet know about the change.

Note: The typical cases for uploading files (v0 or vN) line up with with the keyword and badges cases. For a v0 upload self knows about the change but others don't yet know. For a vN upload (i.e., so far this has been for a comment), self knows about the change, but others don't yet know.

crspybits commented 3 years ago

My plan is to add a table to the server that tracks when specific changes should be indicated as "downloadable" to the user. These table entries will be returned as part of FileIndex results when a summary is requested (not a FileIndex for a specific sharing group). The entries will expire -- say in a week -- so that we don't accumulate too many of them in the table, and also have to return too many of them in a FileIndex request.

Each Upload request will have to supply this information-- what users need to have their album marked as downloadable as a result of a specific change to a file. Those change include both v0 files and vN files.

crspybits commented 3 years ago

With the change to informAllButSelf, and using that for album download indicators, I'm no longer getting the download indicator set if a user is invited to an album and that album has no informAllButSelf records. This seems like the same situation has I'd considered before where someone hadn't used the app for some number of days-- when all of the informAllButSelf records had expired.

I need a fallback for this condition. Options:

  1. I could use just the iOSBasics method objectsNeedingDownload(sharingGroupUUID: UUID). But, when would I call that method? Anytime I get a negative result from my current method in Neebla informUserAboutSharingGroup() (which is based on the informAllButSelf records)? No. Because that would defeat the purpose of the informAllButSelf records-- it would always indicate there was a download available even if the user themselves had made the change.
  2. I could use a last-synced date per album in Neebla. If (a) the current album download indicator is false, (b) informUserAboutSharingGroup() returns false and (c) the last sync date was too long ago, I could then fallback to objectsNeedingDownload(sharingGroupUUID: UUID). This would mean that every album that you hadn't synced for an interval of time would have its download indicator set to true even if there had been no change made by others to the album and just you had made some changes to the album. (Or if there were some changes made to the album to files that shouldn't be brought to anyone's attention -- e.g., the unreadCounts case in https://github.com/SyncServerII/Neebla/issues/15#issuecomment-850735201).

What if I updated a last-synced date for an album when the general sync (not album specific) was done? That way, it wouldn't force the album indicator to be set to true unless the app hadn't been used (i.e., no general sync) for an interval of time. This would also cover the case of just having been invited to an album.

objectsNeedingDownload isn't the right method to use of you haven't used a specific album sync though.

crspybits commented 3 years ago

There is another tricky issue with these files representing additional media attributes. That is: Who ought to own them, and when do they get created?

1) New media item case: This is straightforward. Like all other files created when a media item is created, they are owned by the creating cloud storage owner. E.g., the signed in user if they are a cloud storage owner.

2) Existing media item case: All of our existing media items don't have these files. And so a new file needs to be created per media item. This should probably be done on-demand, not all at once just to not load down the system too much. So, for example, when a large image is viewed for a media item that doesn't have the file, it could be created. In this case: Who will own this new file? I think it should be consistent with the "New media item case" and also owned by the original creator of the media item. To do this, we'll have to provide support for other users creating new items as another user.

I'm not sure if this mode of creating a file as a different user should be something controlled by the requesting user. Or if somehow the need for it should be detected by the server. I think it should always be in the context of an existing "object" in Neebla terms. I.e., an existing file group in server terms. So, the FileIndex table will have one or more rows with the existing fileGroupUUID. A client can know it is adding a file to an existing file group-- it will be some conditional code which is effectively doing a migration. There is however, a race condition. Two users could be trying to view the large image for the same media item in Neebla and trying to add the new media attribute file at the same time. One of them should fail. The new media attribute file will have a new fileLabel. The FileIndex has a constraint UniqueFileLabel which enforced uniqueness on fileLabels within file groups.

This is an interesting kind of failure, however. It is a "permanent" failure. One which cannot be resolved by retries. Clients don't have a means currently to deal with this kind of failure.

To reduce the possibilities of this kind of failure, we could have only owning/creating users create the new additional attribute files. This would make the process of migration really slow, however.

crspybits commented 3 years ago

For readCount there is an additional interesting issue that has come up. If the user marks all comments as read for an album this could lead to a large number of uploads-- of changes to media item attribute files -- one per media item reset. But I don't want to have such a possibly large number of simultaneous uploads to the server.

I could make some change in Neebla itself, but I'd need to add some tracker objects to track (and buffer) the intended changes if more than some limit of uploads was started. Or, I could make this change to iOSBasics. This seems a more likely place. I could add a parameter to the configuration on iOSBasics, and before it attempts to start more uploads, it could check for number of uploads first.