Compare commits

...

2 commits

Author SHA1 Message Date
Daniël Franke
5b95636993 [docs] Add db migration tip for slow hardware instances. (#4457)
This PR adds a new section to the documentation to contain workarounds for running
GtS on slow hardware. Right now it only contains a procedure on how to run migrations
on a different database instance in case the original database is too slow to finish
a database migration in a timely manner.

Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4457
Co-authored-by: Daniël Franke <df@ponc.tech>
Co-committed-by: Daniël Franke <df@ponc.tech>
2025-10-05 14:43:09 +02:00
tobi
259fa1ffac [bugfix] Update interaction policies of freshly dereffed statuses if different from last deref (#4474)
# Description

> If this is a code change, please include a summary of what you've coded, and link to the issue(s) it closes/implements.
>
> If this is a documentation change, please briefly describe what you've changed and why.

This pull request adds a check to see whether interaction policy on a refreshed status is different from the interaction policy set on that status before, and updates the status with the new policy if it's changed.

Should fix a pesky issue where folks on v0.19.2 and above still can't interact with statuses they dereferenced before updating.

## Checklist

Please put an x inside each checkbox to indicate that you've read and followed it: `[ ]` -> `[x]`

If this is a documentation change, only the first checkbox must be filled (you can delete the others if you want).

- [x] I/we have read the [GoToSocial contribution guidelines](https://codeberg.org/superseriousbusiness/gotosocial/src/branch/main/CONTRIBUTING.md).
- [x] I/we have discussed the proposed changes already, either in an issue on the repository, or in the Matrix chat.
- [x] I/we have not leveraged AI to create the proposed changes.
- [x] I/we have performed a self-review of added code.
- [x] I/we have written code that is legible and maintainable by others.
- [x] I/we have commented the added code, particularly in hard-to-understand areas.
- [ ] I/we have made any necessary changes to documentation.
- [ ] I/we have added tests that cover new code.
- [x] I/we have run tests and they pass locally with the changes.
- [x] I/we have run `go fmt ./...` and `golangci-lint run`.

Reviewed-on: https://codeberg.org/superseriousbusiness/gotosocial/pulls/4474
Reviewed-by: kim <gruf@noreply.codeberg.org>
Co-authored-by: tobi <tobi.smethurst@protonmail.com>
Co-committed-by: tobi <tobi.smethurst@protonmail.com>
2025-10-05 13:33:16 +02:00
4 changed files with 132 additions and 1 deletions

View file

@ -0,0 +1,43 @@
# Managing GtS on slow hardware
While GoToSocial runs great on lower-end hardware, some operations are not practical on it, especially
instances with the database on slow storage (think anything that is not an SSD). This document
offers some suggestions on how to work around common issues when running GtS on slow hardware.
## Running database migrations on a different machine
Sometimes a database migration will need to do operations that are taxing on the database's storage.
These operations can take days if the database resides on a hard disk or SD card. If your
database is on slow storage, it can save a lot of time to follow the following procedure:
!!! danger
It might seem tempting to keep GtS running while you run the migrations on another machine, but
doing this will lead to all the posts that are received during the migration post disappearing
once the migrated database is re-imported.
1. Shut down GtS
2. Take a [backup](backup_and_restore.md#what-to-backup-database) of the database
3. Import the database on faster hardware
4. Run the GtS migration on the faster hardware
5. Take a backup of the resultant database
6. Import the resultant backup and overwrite the old database
7. Start GtS with the new version
### Running GtS migrations separately
After you import the database on the faster hardware, you can run the migration without starting
GtS by downloading the *target* GtS version from the [releases](https://codeberg.org/superseriousbusiness/gotosocial/releases) page.
For instance, if you are running `v0.19.2` and you want to upgrade to `v0.20.0-rc1`, download the
latter version. Once you have the binary, set it to executable by running `chmod u+x /path/to/gotosocial`. Afterwards, copy the configuration of the original server, and alter
it with the location of the new database. We copy the configuration in case variables like
the hostname is used in the migration, we want to keep that consistent.
Once everything is in place, you can run the migration like this:
```sh
$ /path/to/gotosocial --config-path /path/to/config migrations run
```
This will run all the migrations, just like GtS would if it was started normally. Once this is done
you can copy the result to the original instance and start the new GtS version there as well, which
will see that everything is migrated and that there's nothing to do except run as expected.

View file

@ -608,6 +608,9 @@ func (d *Dereferencer) enrichStatus(
return nil, nil, gtserror.Newf("error populating emojis for status %s: %w", uri, err)
}
// Check if interaction policy has changed between status and latestStatus.
interactionPolicyChanged := status.InteractionPolicy.DifferentFrom(latestStatus.InteractionPolicy)
if isNew {
// Simplest case, insert this new remote status into the database.
if err := d.state.DB.PutStatus(ctx, latestStatus); err != nil {
@ -625,6 +628,7 @@ func (d *Dereferencer) enrichStatus(
tagsChanged,
mediaChanged,
emojiChanged,
interactionPolicyChanged,
)
if err != nil {
return nil, nil, gtserror.Newf("error handling edit for status %s: %w", uri, err)
@ -1057,6 +1061,7 @@ func (d *Dereferencer) handleStatusEdit(
tagsChanged bool,
mediaChanged bool,
emojiChanged bool,
interactionPolicyChanged bool,
) (
cols []string,
err error,
@ -1141,6 +1146,15 @@ func (d *Dereferencer) handleStatusEdit(
// been previously populated properly.
}
if interactionPolicyChanged {
// Interaction policy changed.
cols = append(cols, "interaction_policy")
// Int pol changed doesn't necessarily
// indicate an edit, it may just not have
// been previously populated properly.
}
if edited {
// Get previous-most-recent modified time,
// which will be this edit's creation time.

View file

@ -17,6 +17,8 @@
package gtsmodel
import "slices"
// A policy URI is GoToSocial's internal representation of
// one ActivityPub URI for an Actor or a Collection of Actors,
// specific to the domain of enforcing interaction policies.
@ -232,6 +234,39 @@ type PolicyRules struct {
ManualApproval PolicyValues `json:"WithApproval,omitempty"`
}
// DifferentFrom returns true if pr1 and pr2
// are not equal in terms of nilness or content.
func (pr1 *PolicyRules) DifferentFrom(pr2 *PolicyRules) bool {
// If one PolicyRules is nil and
// the other isn't, they're different.
if pr1 == nil && pr2 != nil ||
pr1 != nil && pr2 == nil {
return true
}
// Check if AutomaticApproval
// differs between the two.
if slices.Compare(
pr1.AutomaticApproval,
pr2.AutomaticApproval,
) != 0 {
return true
}
// Check if ManualApproval
// differs between the two.
if slices.Compare(
pr1.ManualApproval,
pr2.ManualApproval,
) != 0 {
return true
}
// They're the
// same picture.
return false
}
// Returns the default interaction policy
// for the given visibility level.
func DefaultInteractionPolicyFor(v Visibility) *InteractionPolicy {
@ -422,3 +457,41 @@ func DefaultInteractionPolicyDirect() *InteractionPolicy {
*c = *defaultPolicyDirect
return c
}
// DifferentFrom returns true if p1 and p2 are different.
func (ip1 *InteractionPolicy) DifferentFrom(ip2 *InteractionPolicy) bool {
// If one policy is null and the
// other isn't, they're different.
if ip1 == nil && ip2 != nil ||
ip1 != nil && ip2 == nil {
return true
}
// If they're both nil we don't
// need to check anything else.
if ip1 == nil && ip2 == nil {
return false
}
// If CanLike differs from one policy
// to the next, they're different.
if ip1.CanLike.DifferentFrom(ip2.CanLike) {
return true
}
// If CanReply differs from one policy
// to the next, they're different.
if ip1.CanReply.DifferentFrom(ip2.CanReply) {
return true
}
// If CanAnnounce differs from one policy
// to the next, they're different.
if ip1.CanAnnounce.DifferentFrom(ip2.CanAnnounce) {
return true
}
// Looks the
// same chief.
return false
}

View file

@ -38,7 +38,7 @@ plugins:
extra:
alternate:
- name: English
link: /en/
link: /en/
lang: en
- name: 中文
link: /zh-cn/
@ -149,6 +149,7 @@ nav:
- "admin/spam.md"
- "admin/database_maintenance.md"
- "admin/themes.md"
- "admin/slow_hardware.md"
- "Federation":
- "federation/index.md"
- "federation/http_signatures.md"