Monday, February 18, 2013

[Russian] Olga's Potato Perushky / Perushki / Piroshki / Piroshki

*Phew*  For a minute there, I thought this was the last of the Great Olga Recipes (I pronounce it that way, to my friends).  I still have a couple left.

It's a hard call as to which of Baba's recipes are my favorite.  Which, honestly, is why I've been working on this for the past 5 years.  She's 95 now; I want to make sure these recipes are preserved for me, my family, and the rest of my family (shout-out to the cousins!).  We're extraordinarily lucky she's still around for my daughter.  And I'm extraordinarily lucky that I figured out that I needed to learn these recipes.

Anyhow - this is about as fine a fried potato food as it's possible to get.  Yes, it takes some time to make.  Holy heck, though, it's worth the time and effort.

Cook time: about an hour:
Prep time: 3-4 hours
0: Read completely before doing.  Just because the dough is "A" doesn't mean that's the first thing to do.  In fact, here's my order:
1) Cut & fry onions
2) Make dough, let rise
3) Cut and boil potatoes
4) assemble potato & onion mixture
5) cut/assemble
6) fry

A: The Dough
6 cups sifted Gold Medal All-Purpose flour.  Right around 2 pounds.
1/2 stick butter room temperature or melted
3 tbl Mazola oil
1.5 tsp salt
1.5 packages Active Dry yeast
1.5 cups warm milk ("little warm") - since it's for proofing, 100-110 F.
2 tbl sugar
3 Jumbo Eggs (4 Extra Large)

  • Proof yeast: once your milk is up to temp, add yeast and stir well so that it's all wet.  Let sit 5-10 minutes (honestly, while you get everything else lined up is fine).
  • Beat eggs with sugar and salt. Whisk or fork will work.
  • Now mix all ingredients together in a large bowl until it comes together.  At this point, it'll probably be a bit wet. 
  • Knead one minute.  As you do this, it will firm up.  It won't be tight, it won't be soft, and it WON'T be sticky.  My hands come out of this perfectly dry.  Texture-wise, a little plasticine.
  • Put back in bowl, cover with a slightly-damp tea towel, and stick in the oven (which doesn't get turned on) with the light on inside.  This provides enough heat, the towel enough moisture.  Let rise until double
B: The filling
5-6 medium russet potatoes
3-4 medium size yellow onions. (Personally, I use 3-4 Texas 1015 onions - large and sweet).  
1/2 stick butter or 3 tbl Mazola.
1.5 teaspoons salt (for onions)
1.5 teaspoons salt (for potatoes)

  • Chop onions fine and add salt.  I'd say a plain chop; cut the stem end off, cut the onion in half, straight down from pole to pole, remove peel, cut each half in 1/4ths from the root end (leaving connected), then slice perpendicular to those cuts, about 1/4" thick.  Here's a page, hopefully it stays up for a while: 
  • Simmer onions in 1/2 stick butter, medium heat, until they turn golden brown or mahogany in color.  This can take a few hours on medium (4-5 on my stove).  You can get it down to an hour or so if you turn up the heat to 8 or so until they fry for a bit and the water comes out, then turn down to medium/medium-low.  This is, honestly, the part that takes longest.  Alton Brown does an episode about caramelizing onions for French Onion Soup; his have nothing on Olga's.  I also found this page which seems close. 
  • Dice potatoes into 3/4" to 1" cubes. Boil in a large pot with 1.5 tsp salt.  Time is probably 20 minutes or until tender to the form; you will be mashing them.
  • Once everything's cooked, mix together: onions with all the oil/butter, potatoes, and a healthy several teaspoons of black pepper.  
  • Mash.  You want, honestly, like mashed potatoes. 
  • Taste at this point, add salt and more pepper if necessary.
C: The assembling
  • Take a hunk of dough out and roll into a 2" tube.  Cut into 1" pieces.  
  • At this point you have two options.  One is to flatten them out into rounds, however thin you can get them (my notes say 1/8" thick, but that seems really thick).
    • Alternatively, drop the 1" wide, 2" long piece of dough into a pasta maker.  My pasta maker goes from 1-7.  I use 6: 7 is too thick, and 5 winds up leaving holes in the dough.
  • Once stretched out sufficiently (or as SOON as it comes out of the pasta maker - it shrinks!) put 1 tsp potato mixture (or 1 heaping table spoon, yes, the smallish spoon you use to eat with) in the center.  Alternatively, use a 60 or 70 disher.  I use the 60, but it's a little harder to seal them.  
  • Fold the circle in half and crimp the edges.  Make sure the crimp is good.  The potato mixture should be a ball that fills up the center of your half-circle. That's fine.  Now place this half-circle perpendicular to the table, curved side down, and push gently on the table so that it flattens in the opposite direction.  Repeat 100 times or so.
C1: Alternative assembly directions
This is from my Meat Perushky, which is very similar.  Since I'm using the same filling amount, it should work just the same:

For each perushky, pull off 24-26 grams of dough. 
Two ways to make:
1) stretch out by hand
2) roll and cut
My grandmother stretches it out to a 3.25" circle, thinner at the edges. This is a little heavy on the bread for my taste, so I roll out with a rolling pin until about 3.5 - 4.0 inches around, then use the top of a 3.25" restaurant tumbler (do a Google image search - about 2.75 inches at the bottom and straight sides) to cut out a circle. When I weight it, it comes out to about 18g.

Now take this circle of dough, stretch it out a little, and immediately drop in a dollop of meat potato.  I use a #70 disher - Baba uses a heaping tablespoon. Put this in the middle, then bring the sides together, forming a half-circle. Pinch down repeatedly to seal, squeezing hard with your fingers. Now flatten - put perpendicular to table, round side facing down, and push. It'll wind up as a small round object. Check for seam splits and close them.

D: The Frying:
1 quart Wesson (probably less)

  • In a frying pan, heat 1-1.5 inches of oil to about 300 Fahrenheit, or until you can toss in a piece of dough and have it "fry gently".  
  • Add 6-10 perushky (depending on your pan), SEAM SIDE DOWN, and allow to fry for a minute or so, until the bottom is Golden Brown & Delicious (GBD).  Flip over.  Once cooked on both sides, pull out and add more.  We've found that adding one after you remove one is the best way to avoid over-heating the oil.  

Serve: with Borscht.  Or on a plate. Or as they come out of the frying pan.  Up to you.  They don't keep readily - stick em in a big container and they all go limp on the outside.  Still eminently edible, but a pale shadow of coming out of the fryer.  Oven will perk them up decently, though .

Thursday, February 7, 2013

[Powershell] Running sp_blitz against multiple servers in parallel, saved to table

(update 2013/06/13: I've superceded this with a new framework that will run almost any piece of code, powershell or sql, saving the results to a table, and running with multiple threads. Please give it a look! )

(update 2013/02/09: for some reason, running with only 6 threads doesn't bring back all the servers.  Using 20, however, does.  Odd, and not expected, and obviously I need a better fix)

(update 2013/02/08: if results from sp_blitz aren't saved for a particular server, run the invoke-sqlcmd2 command for sp_blitz against just that server, manually. For sp_blitz we've found a couple bugs and are sending them to Brent Ozar to fix.  Right now, if there are any errors thrown, even if there are results, then invoke-sqlcmd2 doesn't work right.)

So, I recently found out WHY sp_blitz is awesome, and why "30 second takeover" is a horrid subtitle for it. (I always thought that it meant "break into a SQL server in 30 seconds", so I never went - NOPE).

Anyhow, sp_blitz itself is handy as heck - gets a list of common problems that a particular server has, when it gets handed to you and you basically "takeover" and become its DBA in a matter of 30 seconds.

So, the next thing I wanted to do was save the results to a centralized table.  Actually raced a coworker to do it - he did one in SSIS, naturally I wanted it in Powershell.  Later we plan to do "server thunderdome" and see whose runs fastest.

NOTE: this is almost exactly the same code as in my earlier post . The biggest change is the addition of a ServerName field (which was a lot harder to figure out than you'd think, so many thanks to Chad Miller for the fix, and Graimer for a shorter version).  Given it wasn't a simple thing (for me) to add, and what I'm doing with it, I figure it'd be worth another post.

Future changes: I think I'm going to modify it so it looks at a folder, running each script from that folder and saving it to a table named for that script.  Also getting it to return errors; between invoke-sqlcmd2 and the scriptblock, it basically eats any errors and you never see them.  Need to get that working better.

So, first, create a table to hold the data:

CREATE TABLE [dbo].[BlitzResults](
[Priority] [tinyint] NULL,
[FindingsGroup] [varchar](50) NULL,
[Finding] [varchar](200) NULL,
[DatabaseName] [varchar](50) NULL,
[URL] [varchar](200) NULL,
[Details] [nvarchar](4000) NULL,
[QueryPlan] [xml] NULL,
[QueryPlanFiltered] [nvarchar](max) NULL,
[CheckID] [int] NULL,
[ServerName] [varchar](50) NULL

Make sure to save the invoke-sqlcmd.ps1 and the write-datatable.ps1 scripts to a folder (c:\sql_tools, change it however you want).

Now create this script:

#Run SQL query against multiple servers in parallel, saving results to a central table
# 1.00 2012/12/13 mdb / TBD.  Initial release
# 1.10 2012/12/13 mdb / TBD.  Adding throttling scheduler
# 1.11 2012/12/13 mdb adding comment on WHY you want the wait-job
# 1.20 2012/02/07 mdb adding a ServerName field to the datatable. Now we can do sp_blitz w/o modifying it!
# Code cribbed and lessons learned courtesy of: Hey Scripting Guy,
# Aaron Bertrand (the bit with $args[0], his "sad panda face" post)
# Kendra Little
# Throttling scheduler is from "start-automating" Stackoverflow.
# Additional Servername field from Chad Miller and Graimer (stackoverflow)
# Errors are mine, not theirs.
# Please keep this header and let me know how it works.
# Prerequisite: invoke-sqlcmd2 and write-datatable, courtesy of Hey Scripting Guy & Chad Miller
# Long header courtesy of .... um, me.
. C:\sql_tools\invoke-sqlcmd2.ps1;
#get list of servers that meet our criteria; our code will run against these
$serverlist = invoke-sqlcmd2 -serverinstance "ftw-test-08" `
-query "SELECT server FROM yourlistofservershere WHERE active = 1 and version >=9 order by server"
foreach ($server in $serverlist)
    #job running code; allows us to multithread.  -le 8 means 8 jobs run at once. As one drains, the next picks up
    $jobsrunning = @(Get-Job | Where-Object { $_.JobStateInfo.State -eq 'Running' })
    if ($jobsrunning.Count -le 8)
        start-job -argumentlist $server.server -scriptblock `
        #a scriptblock is a wholly separate 'environment'; have to reinvoke functions and reintroduce variables
        . C:\sql_tools\invoke-sqlcmd2.ps1;
        . C:\sql_tools\write-datatable.ps1;
        $server2 = $args[0]

        $quer = invoke-sqlcmd2 -serverinstance $server2 -database "master" `
            -query "exec master.dbo.sp_blitz" -As 'DataTable'


        $quer | %{$_.ServerName = $server2}

        Write-DataTable -ServerInstance "repositoryserver" -Database "dba_stuff" -TableName "BlitzResults" -Data $quer
        $jobsrunning | Wait-Job -Any  #as soon as any job finishes, push the next up

#Now that we're finished, cleanup and get rid of any errant jobs  
get-job | wait-job -timeout 120         #wait 120 seconds or until all jobs are done, whichever comes first

get-job|Remove-Job -force              #cleanup and remove the jobs