Skip to content

Instantly share code, notes, and snippets.

@technosophos
Forked from AeroNotix/gist:5247096
Last active December 15, 2015 12:09
Show Gist options
  • Save technosophos/5258706 to your computer and use it in GitHub Desktop.
Save technosophos/5258706 to your computer and use it in GitHub Desktop.
One way of making it easy to construct new service instances, hide the implementation details, but separate the services. One big advantage in doing things this way is that you could pretty easily create tools to deal with multiple azs, regions, and geos. E.g. you could copy objects from USWest to USEast.
/* hpcloud */
import "hpcloud/objectstorage"
type Account struct {
// Stuff
}
func (a Account) ObjectStorage(region) {
/* Look up the endpoints and stuff...
* Basically making this up as I go.
*/
url := a.UrlFromCatalog("swift", region)
return objectstorage.NewFromAccount(a.Token(), url /* and whatever else */)
}
/* in hpcloud/objectstorage */
func NewFromAccount(token, url /* whatever else... */ ) ObjectStore {
os := new(ObjectStore)
os.token = token
os.url = url
}
type ObjectStore struct {
token string
url string
}
func (o ObjectStore) CreateContainer(containerName string) {}
/* And so on... */
/* Usage would then be like this: */
// For some Account a...
mystore := a.ObjectStorage("region-a.geo-1")
mystore.CreateContainer("foo")
@AeroNotix
Copy link

Hi,

This indeed seems like a nice way to do this. I actually really like this. It's practically the same API besides constructing the various endpoints and passing the token between them.

However, I eventually wanted to add something like parsing the expires token and sticking a goroutine on a <-time.After() call which will then re-authenticate. The reason for this is that since Go is intended to be server-side and I am writing apps which will be long-lived. I don't want to have to make re-authenticate calls.

How would you get around that approach? Maybe internally they could have something like:

/* Unexported */
type authentication struct {
    auth_token string
    m          sync.Mutex
    /* Any other required fields */
}

func (a authentication) authenticate() string {
    a.m.Lock()
    defer a.m.Unlock()
    return a.auth_token
}

func (a *authentication) watch_for_timeout(timestring string) {
    t := parseTimestring(timetsring)
    go func() {
        for {
            <-time.After(t)
            a.m.Lock()
            re_authenticate(a)
            a.m.Unlock()
        }
    }()
}

func Authenticate(u, p, t string) *Account {
    /* Authenticate here */
    a := &authentication{auth_token: response.Token}
    a.watch_for_timeout(timeoutstring)
    acc.authentication = a
}

func NewFromAccount(a authentication /* whatever else */) ObjectStore {
    os := new(ObjectStore)
    os.authentication = a
    os.url = url
}

That's a quick bit of code (it probably (definitely!) won't compile). The assumed function is parseTimestring.

Thoughts on something like this? Otherwise de-authentication/token expiry requires explicit checking of response codes (and subsequent re-creation of all other module values.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment