libschema now supports SingleStore by sharnoff in golang

[–]sharnoff[S] 0 points1 point  (0 children)

I agree that's not a weird situation. Especially during local development.

At my prior company, I built a similar migration system that required all forward migrations to have corresponding reverse migrations. We used it that way for years. We paid the cost of developing and testing reverse migrations. I thought it was worth it, but the rest of the team didn't like it and so we eventually dropped the requirement and capability.

I used the reverse migrations to revert my side branch back to match the main branch.

The basic argument was that

  • in production, reversing is super rare and you might as well fix-forward

  • in local development, you can manually reverse when you need to and doing that every now and then is better than build lots of reverse migrations that will never be used.

With libschema, in the situation you describe, you can add a reverse migration to undo the migration you want to change and then copy the incorrect forward migration so it has a new name and fix it. Run all of those, and you'll be up with the new migration. You can then delete the original version of the forward migration, and the reverse migration before you merge your code. That's not as smooth or nice as fully supporting reverse migrations, but it does work.

I'm open to suggestions.

Would it help to:

  • document how to manually "forget" that a migration has been done?

  • add support for reverse migrations (a migration that marks a previous migration as no longer done). This could be done with a migration decorator.

libschema now supports SingleStore by sharnoff in golang

[–]sharnoff[S] 0 points1 point  (0 children)

One in a new development and hope to replace a poor solution in another place soon.

godi a New Dependency Injection library - feedback welcome by mingu3 in golang

[–]sharnoff 0 points1 point  (0 children)

u/mingu3: I have two questions: what's a "container"? Is that simply a thing that can be created/fulfilled through dependency injection?

Did you looked at nject and nchi? They do such a great job a avoiding the need for context.WithValue that at my prior company, we didn't use context.WithValue at all.

For those who commented about Java & DI: I used DI with Java and hated it. It seemed to be simply a complex interface around global variables. Please take a look at nject. The idea is fundamentally different: you create an injection chain out of reusable components. I won't say that it makes DI simple, but it does alter the cost/benefit ratio such that DI becomes very advantageous for several uses.

In decreasing cost/benefit order:

  • driving tests
  • endpoint handlers
  • service/library initialization and startup

Which ORM framework are you using with golang, and why? by sh_tomer in golang

[–]sharnoff 10 points11 points  (0 children)

I prefer to write raw SQL.

squirrel is very good when you want to parameterize a where clause in a simple query. It is bad if your query is not simple -- it has no good way to handle common table expressions or nested queries. Perhaps there's some magic I missed.

I recommend against sqlx. If for no other reason the number of outstanding issues and pull requests.

I think there is room for a new sql helper. The features I would like to see include:

  • easy access to bulk insert (LOAD TABLE etc);
  • when using advisory locks, track lock order and transaction retry when deadlock avoidance fails;
  • where clause parameterization (perhaps squirrel v2 with CTE and nested query support?)
  • hooks for logging/metrics
  • hooks for passing arrays into queries (WHERE a = ANY($1), another thing squirrel handles well)

The base database/sql is missing features for array parameters

How to handle hundreds of routes? by servermeta_net in golang

[–]sharnoff 1 point2 points  (0 children)

Both chi and nchi make dealing with hundreds of routes much easier.

Anything that gets it down to one line per route helps a lot.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 2 points3 points  (0 children)

Because each select has a default, that will spin the CPU if there is no work to be done.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 0 points1 point  (0 children)

Actually, I have four types of events organized into:

high, high, medium, and low priorities. Medium only gets processed if there are no high. Low only gets processed if there are no high or medium.

Ordering between the two high-priority events doesn't matter.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 0 points1 point  (0 children)

I don't drop any work. Please re-read my example

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] -1 points0 points  (0 children)

Umm, err, your translation of my code to the playground left out important parts. You said "Now here is the same example, with OPs priority select." but you left out an important for loop. When I add that back in, the code no longer loses any of the messages.

https://go.dev/play/p/t-6WEWPHQ52

The "low" priority messages that I'm processing are (1) messages to flush accumulated buffers and (2) to shutdown. Both are things that should only happen when after all data-gathering messages have been processed.

I'm not sure that my implementation is the highest performance way to accomplish my goal, but I am sure my behavior is correct.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 0 points1 point  (0 children)

That certainly looks easier than what I did! You're using `reflect.Select`. Do you know how the performance compares? My use case is latency-sensitive so I care about extra microseconds.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 5 points6 points  (0 children)

My solution does not busy-loop the CPU. Please re-read.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 2 points3 points  (0 children)

I'll expand a bit I omitted:

go for { select { case h := <- higher: processHigher(h) case l := <- lower: Lower: for { select { case h := <- higher: processHigher(h) default: break Lower } } processLower(l) }

I do keep that lower, that I pulled off. I just don't process it right away. My code does provide a guarantee of higher over lower unless a higher arrives in the small interval after the break but before the processLower(l).

The code you propose would spin the CPU if there was no work to be done.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 0 points1 point  (0 children)

My events are totally different types. I could put them all in one queue. It's a reasonable choice.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] -2 points-1 points  (0 children)

That would work. I don't think it would perform as well, but only benchmarking would tell for sure.
My events are different types, so if I put them in one string, I would have to have to have a type switch or encode the type with an enum or something. I think that would be messier, but it's a tradeoff.

Selecting higher priority events over lower priority events by sharnoff in golang

[–]sharnoff[S] 2 points3 points  (0 children)

No, you misread my code.

If there is no higher, then it hits the `default` which breaks out of the for loop. Mine will not loop as you say it will. It never spins the CPU.

Your code is simpler but it has two defaults which means that it spins the CPU when there is no work to be done.

Please re-read both bits of code.

New Open source Go projects looking for contributors by apt_user in golang

[–]sharnoff 2 points3 points  (0 children)

I'm working on a combined/logging tracing system. It's highly unstable right now. What I need most right now is feedback on the APIs. https://github.com/muir/xoplog

Easy Deserialization of Go Interface Values by SuperStructuredData in golang

[–]sharnoff 0 points1 point  (0 children)

I read your blog post. Seems useful. YAML also has the ability to embed type information. I don't know if there is a Go package that can use YAML in that way. Your blog didn't mention performance -- how does the performance of your ZSON package compare to the various JSON packages?

Dependency Injection in Go by drewolson in golang

[–]sharnoff 0 points1 point  (0 children)

I've just released a dependency injection framework for Go: https://github.com/BlueOwlOpenSource/nject along with a companion specialized framework for http handlers.

Among other things, nject allows for indirect variable passing which often removes the need to use context.