Skip to content

Instantly share code, notes, and snippets.

@wejick
Created January 5, 2024 08:49
Show Gist options
  • Save wejick/99064411a9b671ffc3a8d96376835da5 to your computer and use it in GitHub Desktop.
Save wejick/99064411a9b671ffc3a8d96376835da5 to your computer and use it in GitHub Desktop.
package main
import (
"sync"
"github.com/wejick/daging/repo/productcard"
"github.com/wejick/daging/repo/productinfo"
"github.com/wejick/daging/repo/productrating"
"github.com/wejick/daging/repo/shoprating"
)
// Define constants for each RPC call
const (
productInfo = iota
productRating
sid
shopRating
productCard
)
func GetProductCard(productID PID, pc *productcard.ProductCard, pi *productinfo.ProductInfo, pr *productrating.ProductRating, sr *shoprating.ShopRating) productcard.ProductCard {
productInfoChan := make(chan productinfo.ProductInfo)
productRatingChan := make(chan productrating.ProductRating)
sidChan := make(chan SID)
shopRatingChan := make(chan shoprating.ShopRating)
productCardChan := make(chan productcard.ProductCard)
var productInfoResult productinfo.ProductInfo
var productRatingResult productrating.ProductRating
var sidResult SID
var shopRatingResult shoprating.ShopRating
var productCardResult productcard.ProductCard
var wg sync.WaitGroup
// Define the readiness map
ready := [5]bool{}
// Define the dependency matrix
matrix := map[int][]int{
productInfo: {},
productRating: {},
sid: {productInfo},
shopRating: {sid},
productCard: {productInfo, productRating, shopRating},
}
wg.Add(1)
// Start a goroutine for handling incoming data from channels
go func() {
continueLoop := true
for continueLoop {
select {
case productInfoResult = <-productInfoChan:
ready[productInfo] = true
case productRatingResult = <-productRatingChan:
ready[productRating] = true
case sidResult = <-sidChan:
ready[sid] = true
case shopRatingResult = <-shopRatingChan:
ready[shopRating] = true
case productCardResult = <-productCardChan:
ready[productCard] = true
continueLoop = false
}
}
}()
// Start a goroutine for running the RPC calls
go func() {
for {
doingWork := false
for rpc, deps := range matrix {
if !ready[rpc] {
doingWork = true
// Check if all dependencies have finished
allDepsReady := true
for _, dep := range deps {
if !ready[dep] {
allDepsReady = false
break
}
}
// If all dependencies have finished, start the RPC call
if allDepsReady {
switch rpc {
case productInfo:
go func() {
productInfoChan <- ProvideProductInfo(productID, pi)
}()
case productRating:
go func() {
productRatingChan <- ProvideProductRating(productID, pr)
}()
case sid:
go func() {
sidChan <- ProvideSID(productInfoResult)
}()
case shopRating:
go func() {
shopRatingChan <- ProvideShopRating(sidResult, sr)
}()
case productCard:
go func() {
productCardChan <- ProvideProductCard(productInfoResult, shopRatingResult, productRatingResult, pc)
}()
}
}
}
}
// all work has been done
if !doingWork {
wg.Done()
break
}
}
}()
wg.Wait()
return productCardResult
}
// wire.go:
type PID int
type SID int
func ProvideProductRating(productID PID, P *productrating.ProductRating) productrating.ProductRating {
return P.Call(int(productID))
}
func ProvideProductInfo(productID PID, P *productinfo.ProductInfo) productinfo.ProductInfo {
return P.Call(int(productID))
}
func ProvideShopRating(shopID SID, S *shoprating.ShopRating) shoprating.ShopRating {
return S.Call(int(shopID))
}
func ProvideSID(productInfo productinfo.ProductInfo) SID {
return SID(productInfo.ShopID)
}
func ProvideProductCard(productInfo productinfo.ProductInfo, shopRating shoprating.ShopRating,
productRating productrating.ProductRating, P *productcard.ProductCard) productcard.ProductCard {
return P.Call(productcard.Param{
ProductInfo: productInfo,
ShopRating: shopRating,
ProductRating: productRating,
})
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment