Skip to content

feat(libsidecar): worldserver petition validation endpoint + guild.created hook - #57

Closed
3kynox wants to merge 6 commits into
walkline:masterfrom
3kynox:feat/libsidecar-guild-create
Closed

feat(libsidecar): worldserver petition validation endpoint + guild.created hook#57
3kynox wants to merge 6 commits into
walkline:masterfrom
3kynox:feat/libsidecar-guild-create

Conversation

@3kynox

@3kynox 3kynox commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

Reworked per our Discord discussion — this is now the worldserver plumbing for gateway-triggered guild creation instead of a CreateGuild client. Both libsidecar implementations (Go and native C++) gain:

  • a CanTurnInGuildPetition gRPC method on the worldserver service, dispatched on the world update thread through a new TC9SetCanTurnInGuildPetitionHandler binding, so petition validation (charter item, ownership, signatures) stays world-side;
  • a guild.created NATS consumer wired to a new TC9SetOnGuildCreatedHook, so worldservers can populate state for guilds created by the guild service.

Stacked on #55 (proto + RPC it builds on): the net-new commit is the last one. The gateway trigger is #58, the AC-side consumer/handler is the replacement of walkline/azerothcore-wotlk#5.

Copilot AI review requested due to automatic review settings July 15, 2026 21:41

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

Adds end-to-end “create guild” support across the guildserver (RPC + repo + cache + events) and exposes it to the native libsidecar-cpp so the worldserver can route guild creation through the guild service in cluster mode.

Changes:

  • Introduces CreateGuild gRPC RPC (+ generated Go bindings) and corresponding server/service implementations.
  • Adds a guild.created NATS event (producer interface + payload + mock) emitted on guild creation.
  • Adds libsidecar-cpp guild service client wiring and exports TC9GuildCreate, plus config/env plumbing and tests for creation + cache behavior.

Reviewed changes

Copilot reviewed 19 out of 23 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
shared/events/producer-guild.go Extends guild event producer API with GuildCreated publisher.
shared/events/mocks/GuildServiceProducer.go Updates mock to include GuildCreated.
shared/events/events-guild.go Adds GuildEventGuildCreated subject mapping and payload struct.
gen/guilds/pb/guilds.pb.go Regenerates Go protobuf types to include CreateGuild* messages.
gen/guilds/pb/guilds_grpc.pb.go Regenerates Go gRPC bindings to include CreateGuild RPC.
api/proto/v1/guilds/guilds.proto Defines CreateGuild RPC and request/response messages.
apps/guildserver/server/guilds.go Implements gRPC handler for CreateGuild.
apps/guildserver/server/guilds-logger_debug.go Adds debug logging middleware for CreateGuild.
apps/guildserver/service/guilds.go Implements guild creation flow + validation + event emission.
apps/guildserver/service/guilds-cache.go Adds GuildMembershipSource to support bypassing stale cached membership.
apps/guildserver/service/guilds-cache_inmem.go Implements cache eviction-from-source and cache hydration on CreateGuild.
apps/guildserver/service/guilds-create_test.go Adds tests for service-level guild creation behavior.
apps/guildserver/service/guilds-cache_inmem_test.go Adds tests for source-membership eviction + leader-online caching on create.
apps/guildserver/repo/guilds.go Adds ErrGuildNameTaken and CreateGuild repo interface method.
apps/guildserver/repo/mocks/guilds-repo.go Adds repo mock method for CreateGuild.
apps/guildserver/repo/guilds_mysql.go Implements GuildByRealmAndID, CreateGuild, and improves no-rows handling.
game-server/libsidecar-cpp/src/grpc/clients.h Adds guild stub/channel and CreateGuild client method + Connect param.
game-server/libsidecar-cpp/src/grpc/clients.cpp Wires guild channel/stub and implements GrpcClients::CreateGuild.
game-server/libsidecar-cpp/src/core/config.h Adds guild_service_address config getter/member.
game-server/libsidecar-cpp/src/core/config.cpp Loads TC9_GUILD_SERVICE_ADDRESS env var.
game-server/libsidecar-cpp/src/api.cpp Stores realm id on init; exports TC9GuildCreate wrapper.
game-server/libsidecar-cpp/include/libsidecar.h Declares TC9GuildCreate C API with usage contract.
game-server/libsidecar-cpp/CMakeLists.txt Adds guilds.proto to generated proto set.
Files not reviewed (4)
  • apps/guildserver/repo/mocks/guilds-repo.go: Generated file
  • gen/guilds/pb/guilds.pb.go: Generated file
  • gen/guilds/pb/guilds_grpc.pb.go: Generated file
  • shared/events/mocks/GuildServiceProducer.go: Generated file

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +405 to +421
guild, err := g.r.GuildByRealmAndID(ctx, realmID, id)
if err != nil {
return id, fmt.Errorf("guild %d created but not cached, err: %w", id, err)
}

g.cacheMutex.Lock()
g.cache[realmID][id] = guild
for _, member := range guild.GuildMembers {
if member.PlayerGUID == leaderGUID {
// Guild creation is always driven by a live session of the leader,
// but the world may not have flushed the online flag to the
// characters table yet, so the hydration can miss it.
member.Status = repo.GuildMemberStatusOnline
}
g.guildMembersCache[realmID][member.PlayerGUID] = member
}
g.cacheMutex.Unlock()

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added an init guard for the per-realm inner maps before the cache writes.

@3kynox
3kynox force-pushed the feat/libsidecar-guild-create branch from e9eafea to 070ce26 Compare July 17, 2026 19:35
@3kynox 3kynox changed the title feat(libsidecar-cpp): guild service client with CreateGuild export feat(libsidecar): worldserver petition validation endpoint + guild.created hook Jul 17, 2026
@3kynox

3kynox commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Force-pushed a full rework: the CreateGuild client export is gone, replaced by the worldserver validation endpoint and the guild.created hook (both Go and native implementations). Details in the updated description.

@3kynox
3kynox force-pushed the feat/libsidecar-guild-create branch 2 times, most recently from c926147 to 10c879e Compare July 17, 2026 20:22
3kynox added 6 commits July 23, 2026 09:13
Adds a CreateGuild RPC: the guild row, the five default 3.3.5 ranks and the
leader as guild master are inserted in one transaction, the guild id being
allocated as MAX(guildid)+1 with a retry on primary key conflicts (a
worldserver can still create guilds in-process concurrently). The created
guild is cached hydrated and a guild.created event is published.

Also implements the GuildByRealmAndID mysql repo method that was left as
panic("implement me") - the cache needs it to hydrate the new guild.

(cherry picked from commit 3608d5a3f14348c31ca54faafb07f27948919bfc)
…ild creation

The world can disband guilds without going through the guild service
(e.g. GM .guild delete handled in-process), leaving a stale positive
membership in the in-memory cache. CreateGuild now rechecks a positive
answer against the database and evicts the stale cache entry, instead
of rejecting with 'already in guild' until the service restarts.

Also treats a missing guild_member row as 'not in a guild' in the MySQL
repo instead of surfacing sql.ErrNoRows.

(cherry picked from commit 2c779169db1722cb20bfa58faf8674a482af09f1)
Guild creation is always driven by a live session of the leader, but in
cluster mode the world doesn't flush the online flag to the characters
table, so the hydration read the leader back as offline. This left the
fresh guild with an empty online-members list: the roster showed the
leader disconnected and guild events (e.g. MOTD updates) were broadcast
to nobody until the leader relogged.

(cherry picked from commit 7000ccaa6c9f19ce89c1f3884f355243a74628d9)
…ity)

The core's CreateDefaultGuildRanks gives both Guild Master and Officer
GR_RIGHT_ALL; the service only gave the Officer chat rights, so a freshly
promoted officer had every guild action greyed out client-side (invite,
promote, etc.). Match the core layout and assert it in the create test.
- CreateGuildParams gains signatoryGUIDs; members are inserted with the
  lowest rank in the same transaction, skipping characters that joined
  another guild since signing.
- guild.created event now carries the added member guids so worldservers
  can populate the state for the new guild.
- New worldserver RPC CanTurnInGuildPetition for the gateway to validate
  petitions on the worldserver side before calling CreateGuild.
…eated hook

Both implementations (Go and native C++) gain:
- CanTurnInGuildPetition gRPC method dispatched on the world update
  thread through a new TC9SetCanTurnInGuildPetitionHandler binding;
- a guild.created NATS consumer that calls the new TC9SetOnGuildCreatedHook
  so worldservers can populate state for guilds created by the guild service.
@3kynox
3kynox force-pushed the feat/libsidecar-guild-create branch 2 times, most recently from 10c879e to 22f4f21 Compare July 23, 2026 07:16
@3kynox

3kynox commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Superseded by #81, which regroups the guild creation work into a single PR as discussed. Same content, rebased on current master, with the review points from this PR already applied.

@3kynox 3kynox closed this Jul 26, 2026
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.

2 participants