Here’s AN approach, which is simple but assumes you won’t have thousands of documents and/or you’re fine with waiting a bit for them to load:
Use indices (1, 2, 3…) as unique keys in the documents DataStore. Make sure to set a limit for the length of the text of each document. Use another key (e.g. “counter”) to keep track of the number of documents.
When the server starts, get the counter value, and then start getting the documents one by one up until the counter value. Once that is reached, keep checking the counter value for a change, repeating the previous step when it changes. You have a 60 requests/minute budget for GET requests regardless of the number of players, so I’d personally add a 1 second wait between all requests that relate to the documents (including counter checks, and getting the documents that need to be reviewed), that would use even less than 60/min.
There are different ways of communicating changes to the clients, like RemoteEvents or adding Folders with different ValueBases in ReplicatedStorage, it’s up to you. Though whatever you do I’d say: to keep memory free, don’t transfer the text to the clients until they ask for a specific document, and make sure to free that up too once they’re done with it.
Keep the submitted documents in a separate DataStore, make sure to limit how often clients can submit (e.g. a 1 minute cooldown). Use :ListKeysAsync()
on that DataStore for moderators, when they want to review documents, and then fetch the one they want to review through the delayed fetching system, but push these requests to the front of the queue, so they don’t have to wait for all the accepted documents to be fetched. Make sure to remove such requests from the queue if the moderator isn’t trying to view a submitted document anymore (they clicked away or left). It would also be good to test if :ListKeysAsync()
uses up the budget, and then incorporate it into the queued system as well if it does.
Both accepted and rejected documents should be removed from the submissions DataStore, and if they are accepted they should be moved to the documents DataStore: :IncrementAsync()
the counter key, and then SetAsync()
the new document with the key that IncrementAsync returned. That way there should be no issues with servers writing to the same key, and you won’t need a complex tracking system. Though you should still take into account the possibility of two moderators making a decision about the same document, there are also multiple ways to solve that, but the easiest would be to try to get the same key (from submissions) once a moderator makes a decision, and then if it doesn’t exist (because it gets removed in both cases) don’t do anything, maybe inform the moderator that a decision was already made.
I haven’t talked about keys for the submissions DataStore, but tostring(os.clock())
would be an easy option.
That’s pretty much it, unless I’m forgetting something.
As for folders and sub-folders (alternatively “tags” or “categories”), the moderators can just add those as part of the document data (some multiple-option selection that you set). Clearance could be either manually set by moderators, or based off of folders and/or categories. I’d say do server checks for everything moderators do as well, you never know.
Let me know if you want me to address something else, or if I should expand on something. Some things do depend on what you’re planning to do in the future, but as for your current idea I think this is about as simple (but stable) as it can get, provided you’re fine with waiting for the documents a bit, if there’s ever many of them. If you want them fetched quicker, you’d have to do a more complex system where you’re storing many of them per key, and the complexity lies in making sure the servers don’t overwrite “each-other”, because the simple counter system wouldn’t be suitable there.