-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(OraklNode) Libp2p reconnect attempt after disconnection (#1799)
* feat: reconnection support * feat: prevent duplicate url inserts * fix: remove unused features * fix: simplify subscription code * feat: admin function to for `sync` and `peerCount` * fix: add go task, rename bus message type * fix: add minor log and update test * fix: update based on feedback * fix: update based on feedback * feat: handle default
- Loading branch information
1 parent
979dc78
commit 7403efd
Showing
16 changed files
with
411 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
ALTER TABLE peers DROP CONSTRAINT IF EXISTS unique_url; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
ALTER TABLE peers DROP CONSTRAINT IF EXISTS unique_url; | ||
ALTER TABLE peers ADD CONSTRAINT unique_url UNIQUE (url); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
package host | ||
|
||
import ( | ||
"bisonai.com/orakl/node/pkg/admin/utils" | ||
"bisonai.com/orakl/node/pkg/bus" | ||
"github.com/gofiber/fiber/v2" | ||
"github.com/rs/zerolog/log" | ||
) | ||
|
||
func getPeerCount(c *fiber.Ctx) error { | ||
msg, err := utils.SendMessage(c, bus.LIBP2P, bus.GET_PEER_COUNT, nil) | ||
if err != nil { | ||
log.Error().Err(err).Str("Player", "Admin").Msg("failed to send message to libp2p helper") | ||
return c.Status(fiber.StatusInternalServerError).SendString("failed to get peer count: " + err.Error()) | ||
} | ||
resp := <-msg.Response | ||
if !resp.Success { | ||
log.Error().Str("Player", "Admin").Msg("failed to get peer count: " + resp.Args["error"].(string)) | ||
return c.Status(fiber.StatusInternalServerError).SendString("failed to get peer count: " + resp.Args["error"].(string)) | ||
} | ||
|
||
return c.JSON(resp.Args) | ||
} | ||
|
||
func sync(c *fiber.Ctx) error { | ||
msg, err := utils.SendMessage(c, bus.LIBP2P, bus.LIBP2P_SYNC, nil) | ||
if err != nil { | ||
log.Error().Err(err).Str("Player", "Admin").Msg("failed to send message to libp2p helper") | ||
return c.Status(fiber.StatusInternalServerError).SendString("failed to sync libp2p host: " + err.Error()) | ||
} | ||
resp := <-msg.Response | ||
if !resp.Success { | ||
log.Error().Str("Player", "Admin").Msg("failed to sync libp2p host") | ||
return c.Status(fiber.StatusInternalServerError).SendString("failed to sync libp2p host: " + resp.Args["error"].(string)) | ||
} | ||
|
||
return c.SendString("libp2p synced") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package host | ||
|
||
import ( | ||
"github.com/gofiber/fiber/v2" | ||
) | ||
|
||
func Routes(router fiber.Router) { | ||
host := router.Group("/host") | ||
|
||
host.Get("/peercount", getPeerCount) | ||
host.Post("/sync", sync) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
//nolint:all | ||
package tests | ||
|
||
import ( | ||
"context" | ||
|
||
"testing" | ||
|
||
"bisonai.com/orakl/node/pkg/bus" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestGetPeerCount(t *testing.T) { | ||
ctx := context.Background() | ||
cleanup, testItems, err := setup(ctx) | ||
if err != nil { | ||
t.Fatalf("error setting up test: %v", err) | ||
} | ||
defer cleanup() | ||
|
||
channel := testItems.mb.Subscribe(bus.LIBP2P) | ||
waitForMessageWithResponse(t, channel, bus.ADMIN, bus.LIBP2P, bus.GET_PEER_COUNT, map[string]any{"Count": 1}) | ||
|
||
result, err := GetRequest[struct{ Count int }](testItems.app, "/api/v1/host/peercount", nil) | ||
if err != nil { | ||
t.Fatalf("error getting peercount: %v", err) | ||
} | ||
|
||
assert.Equal(t, 1, result.Count) | ||
} | ||
|
||
func TestSync(t *testing.T) { | ||
ctx := context.Background() | ||
cleanup, testItems, err := setup(ctx) | ||
if err != nil { | ||
t.Fatalf("error setting up test: %v", err) | ||
} | ||
defer cleanup() | ||
|
||
channel := testItems.mb.Subscribe(bus.LIBP2P) | ||
waitForMessage(t, channel, bus.ADMIN, bus.LIBP2P, bus.LIBP2P_SYNC) | ||
|
||
result, err := RawPostRequest(testItems.app, "/api/v1/host/sync", nil) | ||
if err != nil { | ||
t.Fatalf("error sync libp2p host: %v", err) | ||
} | ||
|
||
assert.Equal(t, string(result), "libp2p synced") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
package helper | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"time" | ||
|
||
"bisonai.com/orakl/node/pkg/bus" | ||
errorSentinel "bisonai.com/orakl/node/pkg/error" | ||
"bisonai.com/orakl/node/pkg/libp2p/setup" | ||
"github.com/libp2p/go-libp2p/core/event" | ||
"github.com/libp2p/go-libp2p/core/host" | ||
"github.com/libp2p/go-libp2p/core/network" | ||
"github.com/rs/zerolog/log" | ||
) | ||
|
||
type App struct { | ||
Host host.Host | ||
Bus *bus.MessageBus | ||
} | ||
|
||
func New(bus *bus.MessageBus, h host.Host) *App { | ||
return &App{ | ||
Bus: bus, | ||
Host: h, | ||
} | ||
} | ||
|
||
func (a *App) Run(ctx context.Context) error { | ||
defer a.subscribe(ctx) | ||
|
||
sub, err := a.Host.EventBus().Subscribe(new(event.EvtPeerConnectednessChanged)) | ||
if err != nil { | ||
return fmt.Errorf("event subscription failed: %w", err) | ||
} | ||
|
||
a.subscribeLibp2pEvent(ctx, sub) | ||
return nil | ||
} | ||
|
||
func (a *App) subscribe(ctx context.Context) { | ||
log.Debug().Str("Player", "Libp2pHelper").Msg("subscribing to libp2pHelper topics") | ||
channel := a.Bus.Subscribe(bus.LIBP2P) | ||
go func() { | ||
log.Debug().Str("Player", "Libp2pHelper").Msg("starting libp2p subscription goroutine") | ||
for { | ||
select { | ||
case msg := <-channel: | ||
log.Debug(). | ||
Str("Player", "Libp2pHelper"). | ||
Str("from", msg.From). | ||
Str("to", msg.To). | ||
Str("command", msg.Content.Command). | ||
Msg("libp2p received bus message") | ||
go a.handleMessage(ctx, msg) | ||
case <-ctx.Done(): | ||
log.Debug().Str("Player", "Libp2pHelper").Msg("stopping libp2pHelper subscription goroutine") | ||
return | ||
} | ||
} | ||
}() | ||
} | ||
|
||
func (a *App) handleMessage(ctx context.Context, msg bus.Message) { | ||
if msg.To != bus.LIBP2P { | ||
log.Debug().Str("Player", "Libp2pHelper").Msg("message not for libp2pHelper") | ||
return | ||
} | ||
if msg.From != bus.ADMIN { | ||
bus.HandleMessageError(errorSentinel.ErrBusNonAdmin, msg, "libp2pHelper received message from non-admin") | ||
} | ||
|
||
switch msg.Content.Command { | ||
case bus.GET_PEER_COUNT: | ||
log.Debug().Str("Player", "Libp2pHelper").Msg("get peer count msg received") | ||
peerCount := len(a.Host.Network().Peers()) | ||
msg.Response <- bus.MessageResponse{Success: true, Args: map[string]any{"Count": peerCount}} | ||
case bus.LIBP2P_SYNC: | ||
log.Debug().Str("Player", "Libp2pHelper").Msg("libp2p sync msg received") | ||
err := setup.ConnectThroughBootApi(ctx, a.Host) | ||
if err != nil { | ||
bus.HandleMessageError(err, msg, "failed to sync through boot api") | ||
return | ||
} | ||
msg.Response <- bus.MessageResponse{Success: true} | ||
default: | ||
bus.HandleMessageError(errorSentinel.ErrBusUnknownCommand, msg, "libp2p helper received unknown command") | ||
return | ||
} | ||
} | ||
|
||
func (a *App) subscribeLibp2pEvent(ctx context.Context, sub event.Subscription) { | ||
go func() { | ||
for { | ||
select { | ||
case <-ctx.Done(): | ||
sub.Close() | ||
return | ||
case e := <-sub.Out(): | ||
a.handleDisconnectEvent(ctx, e) | ||
} | ||
} | ||
}() | ||
} | ||
|
||
func (a *App) handleDisconnectEvent(ctx context.Context, e interface{}) { | ||
log.Info().Str("Player", "Libp2pHelper").Msg("Disconnect event catched, triggering resync") | ||
evt := e.(event.EvtPeerConnectednessChanged) | ||
if evt.Connectedness == network.NotConnected { | ||
for i := 1; i < 4; i++ { | ||
// do not attempt immediate resync, but give some time | ||
time.Sleep(time.Duration(i) * time.Minute) | ||
err := setup.ConnectThroughBootApi(ctx, a.Host) | ||
if err != nil { | ||
log.Error().Err(err).Str("Player", "Libp2pHelper").Msg("Error occurred on boot API sync") | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.