Golang looping through redis store to delete gorilla sessions - go

I am using gorilla sessions.
I have a redis store which has sessions:
here is a sample one:
"session_UDPTLRXUXTJZMVB2AFWRNJHJQXBR27ZY5KZ7Z3KSIXL6ETQ4KXEIBJA4WEVEQID2WSAFQFKLFOHWYT42PIHUMRNW5RWSS76Z72QS4SI"
getting an existing session:
store := redisSessionInstance.Store
session, err := store.Get(c.Request(), "session_")
if err != nil {
return c.String(http.StatusNotAcceptable, "failed getting session")
}
on these sessions is stored an id which identifies the owner.
session.Values["userID"] = existingUser.ID.Hex()
what is the best way to delete all sessions for a user?
I could loop through all the sessions in a for loop and then query the stored value to see if it matches the owners id.
Is there a faster way?

Related

How do I check if the Session object in GoCQL is connected similar to PING in Redis?

Created a cassandra cluster using gocql library.
func CreateCassandraCluster(host string) (*gocql.Session, error) {
cluster := gocql.NewCluster(host)
cluster.ConnectTimeout = time.Second * 10
cluster.DisableInitialHostLookup = true
session, err := cluster.CreateSession()
if err != nil {
return session, err
}
return session, nil
}
my objective is to make a function with *gocql.Session as a argument that will check when passing any cassandra cluster's session is it connected or not connected?
For redis we have PING query to determine redis is connected or not do we have similar thing for cassandra using gocql?
This looks like an identical question you asked yesterday although I can't seem to locate it now so I'm wondering if you deleted it.
It's not obvious to me what you are trying to achieve. Checking if the session is connected or not is not helpful when it comes to Cassandra.
When the driver establishes a connection to the cluster for the first time, it uses the hosts you passed in NewCluster() to do an initial connection to discover the rest of the nodes and the cluster topology (rack configuration, data centres), then establishes connections to the nodes.
If a connection fails, the default policy in the driver is smart enough to automatically reconnect so duplicating this functionality is pointless.
As I stated in your other question, you are better off using free open-source tools like Metric Collector for Apache Cassandra (MCAC) if your ultimate goal is to monitor the health of your Cassandra cluster. Cheers!
Tried this approach where we are going to just check session open or closed
func CheckCassandraHealthCheck(Pool interface{}, Host string, Port int) map[string]interface{} {
response := make(map[string]interface{})
response1 := make(map[string]interface{})
cassandraCluster := Pool.(*gocql.Session)
response["type"] = 4
response1["host"] = Host
response1["PORT"] = Port
if cassandraCluster != nil && !cassandraCluster.Closed() {
response["STATUS"] = constant.UP
response["DETAILS"] = response1
return response
}
response["DETAILS"] = response1
response["STATUS"] = constant.DOWN
return response
Not sure if it is the correct approach or not

How to retrieve last inserted ID in golang go orm when using Raw query

I am using a raw query to create an entry in MySQL,
db.Exec("INSERT STATEMENT")
I want to retrieve the last ID , in the native golang/sql package, it is easy, but here in GORM I can't see anything
I know that using the db.Create can solve my problem, but I have to use Raw query and nothing else
Why do you want to do it with GORM if you are not actually using GORM, but a raw query anyway? GORM exposes the generic database interface through the DB method. So you can do this:
sqlDB, err := db.DB()
res, err := sqlDB.Exec("INSERT STATEMENT")
lid, err := res.LastInsertId()
Of course, you should handle possible errors.

Go Gorm Atomic Update to Increment Counter

I have what is essentially a counter that users can increment.
However, I want to avoid the race condition of two users incrementing the counter at once.
Is there a way to atomically increment a counter using Gorm as opposed to fetching the value from the database, incrementing, and finally updating the database?
If you want to use the basic ORM features, you can use FOR UPDATE as query option when retrieving the record, the database will lock the record for that specific connection until that connection issues an UPDATE query to change that record.
Both the SELECT and UPDATE statements must happen on the same connection, which means you need to wrap them in a transaction (otherwise Go may send the second query over a different connection).
Please note that this will make every other connection that wants to SELECT the same record wait until you've done the UPDATE. That is not an issue for most applications, but if you either have very high concurrency or the time between SELECT ... FOR UPDATE and the UPDATE after that is long, this may not be for you.
In addition to FOR UPDATE, the FOR SHARE option sounds like it can also work for you, with less locking contentions (but I don't know it well enough to say this for sure).
Note: This assumes you use an RDBMS that supports SELECT ... FOR UPDATE; if it doesn't, please update the question to tell us which RDBMS you are using.
Another option is to just go around the ORM and do db.Exec("UPDATE counter_table SET counter = counter + 1 WHERE id = ?", 42) (though see https://stackoverflow.com/a/29945125/1073170 for some pitfalls).
A possible solution is to use GORM transactions (https://gorm.io/docs/transactions.html).
err := db.Transaction(func(tx *gorm.DB) error {
// Get model if exist
var feature models.Feature
if err := tx.Where("id = ?", c.Param("id")).First(&feature).Error; err != nil {
return err
}
// Increment Counter
if err := tx.Model(&feature).Update("Counter", feature.Counter+1).Error; err != nil {
return err
}
return nil
})
if err != nil {
c.Status(http.StatusInternalServerError)
return
}
c.Status(http.StatusOK)

Should there be a new datastore.Client per HTTP request?

The official Go documentation on the datastore package (client library for the GCP datastore service) has the following code snippet for demonstartion:
type Entity struct {
Value string
}
func main() {
ctx := context.Background()
// Create a datastore client. In a typical application, you would create
// a single client which is reused for every datastore operation.
dsClient, err := datastore.NewClient(ctx, "my-project")
if err != nil {
// Handle error.
}
k := datastore.NameKey("Entity", "stringID", nil)
e := new(Entity)
if err := dsClient.Get(ctx, k, e); err != nil {
// Handle error.
}
old := e.Value
e.Value = "Hello World!"
if _, err := dsClient.Put(ctx, k, e); err != nil {
// Handle error.
}
fmt.Printf("Updated value from %q to %q\n", old, e.Value)
}
As one can see, it states that the datastore.Client should ideally only be instantiated once in an application. Now given that the datastore.NewClient function requires a context.Context object does it mean that it should get instantiated only once per HTTP request or can it safely be instantiated once globally with a context.Background() object?
Each operation requires a context.Context object again (e.g. dsClient.Get(ctx, k, e)) so is that the point where the HTTP request's context should be used?
I'm new to Go and can't really find any online resources which explain something like this very well with real world examples and actual best practice patterns.
You may use any context.Context for the datastore client creation, it may be context.Background(), that's completely fine. Client creation may be lengthy, it may require connecting to a remote server, authenticating, fetching configuration etc. If your use case has limited time, you may pass a context with timeout to abort the operation. Also if creation takes longer than the time you have, you may use a context with cancel and abort the mission at your will. These are just options which you may or may not use. But the "tools" are given via context.Context.
Later when you use the datastore.Client during serving (HTTP) client requests, then using the request's context is reasonable, so if a request gets cancelled, then so will its context, and so will the datastore operation you issue, rightfully, because if the client cannot see the result, then there's no point completing the query. Terminating the query early you might not end up using certain resources (e.g. datastore reads), and you may lower the server's load (by aborting jobs whose result will not be sent back to the client).

Go Gorilla Mux Session Name

I am having a hard time understanding Gorilla mux's session name.
http://www.gorillatoolkit.org/pkg/sessions#CookieStore.Get
var store = sessions.NewCookieStore([]byte("something-very-secret"))
func MyHandler(w http.ResponseWriter, r *http.Request) {
// Get a session. We're ignoring the error resulted from decoding an
// existing session: Get() always returns a session, even if empty.
session, _ := store.Get(r, "session-name")
// Set some session values.
session.Values["foo"] = "bar"
session.Values[42] = 43
// Save it.
session.Save(r, w)
}
I want to use session to avoid using global variables between two handlers. So I save the key-value in the shared session and retrieve the value from the session.
And I wonder if I want each user to have its own unique session and its Values, do I need to assign unique session name(session id)? Or the gorilla session handles by itself that each user gets its own session and values?
I wonder if I need to generate session names with unique identifiers.
Thanks
The session data is stored in the client's cookies. So the session you retrieve with store.Get(r, "session-name") is reading that particular client't (request) cookies. You do not need unique names. The name in this case is the name of the cookie so it will be unique to the request.

Resources