Categories
Meta stories

Faster than Light, hyperspace, and how to deal

A common problem with Sci-fi is how to deal with the speed of light.

Why is it interesting, who cares I hear you ask? I suspect some of the most interesting world building and storylines may happen when the corner cases are explored.

Please note, this isn’t real life. Real life is that you can’t go faster than the speed of light. Furthermore, an object with mass can’t even go at the speed of light. (Although I heard a PhD recently say photons may have a tiny mass but look, this isn’t a bleedin cutting edge paper!)

Now, back to the glorious world of sci-fi where we can pick and choose what we write!

There are a few options, and whichever is taken generally impacts the “world building”.

By far the most common way to deal with the speed of light is the ‘universal now’ that is, there is a ‘now’ that is true, whichever your perspective, distance or speed.

The interesting thing about this framework is that most people believe the real world is like this! It works pretty well for sci-fi because of this. It is the invisible way of dealing with light speed in fiction, and is, ahem, generally harmless.

Travel

The boat (Hyperspace); The time taken to travel from one part of the galaxy to the other is akin to a boat ride, very far away takes a long time, so that’s maybe like crossing the ocean. Going to a different galaxy is often ruled out due to this, going to a closer star system, is of course, quicker (culture series), like sailing up the coast perhaps.

The boat and wormhole; Other methods involve “worm holes”, like shortcuts, where your ship can travel slowly, and then go through a worm hole somewhere else instantly or very quickly (expeditionary force).

Sub-light; There is the hibernation options that are sub light speed. Unfortunately this generally means star systems are isolated from each-other in your world. Immortality can also fix this (savages from Galaxy’s Edge).

The set up

Planet ‘Alfalfa’, centre of your universe, Planet ‘Beetroot’ (you are a vegetable orientated species), a light year away. 1LY is not a measure of time, it means 10 trillion kilometres (ish).

The plague planet “Sprout” lies somewhere in the vast expanse between these two herbaceous planets. We don’t like them, they get up to ‘all sorts’.

Sprout likes no one, and has developed a… Hard to call it a weapon, maybe a overly developed sense of personal space? This “definitely not a weapon”, when triggered, can cause both Alfalfa and Beetroot to start moving away from eachother very quickly.

Initially concerned, the great kingdoms on Alfalfa and Beetroot no longer care, because they’ve managed to invent… Wormholes!

How it gets interesting

Here are a few things which I feel would be interesting to explore as a writer. I understand that many have been explored before, but thankfully, it doesn’t mean they can’t be looked at again!

If you were to travel to planet Beetroot at the speed of light; from your perspective, you would arrive instantly. To a photon, it’s journey is instantaneous. This kinda blows the boat analogy out of the water. As a passenger on a light speed ship, there is no delay to your destination once you get to light speed.

To the great vegetarian peoples of Planet Alfalfa however, it would have taken a year for you to get to Beetroot, and they, themselves, would be a year older.

Enders Game (the later ones) explored this problem. People who regularly travelled to other planets, gradually lost all their connections to “back home”. While the travellers stayed the same age, their friends and family left at home all aged and got older. Do this a bit too much and wham, you’re meeting your own grandkids, and they are older than you!

The universe in motion

The ‘universal now’ is great, and we need the universal now for worm holes to work (as the appear in most fiction). The Now is great… until we consider that everything is in motion. Here’s how it breaks causality, or allows ‘time travel’ backwards in time.

Forward in time

Forward in time is easy, as stated above, wormhole to somewhere moving very fast (Beetroot when Sprout is having an ‘off day’), and travel home again. Forwards in time is easy, you just need speed.

Backwards in time was much harder to figure out, until I realised it’s actually the same thing, you just bring the Universal Now with you!

The Great Race

“Every twelve hundred moons, our ancestors have taken part in our most honoured games. The origins of this ancient and noble tradition are lost in the mists of time. Once a century(ish), the greatest families on all Alfalfa supply a team, a team who must compete in the greatest of all races, a race which will decide who rules the great garden of Alfalfa, for the next twelve hundred moons. This race, as you all know, is called ‘Pass the Carrot’….. you back there, stop sniggering!”

“After consulting with the greatest minds and spookiest oracles on Alfalfa, it is decided that ‘Pass Th… I mean… The Great Race’ participants can indeed use our new ‘faster than light, instomatic wormholes’ to complete this holiest of all races. What could possibly go wrong?”

The Parsnip Partnership had a plan. Over the last year they had been coordinating with various succulents on planet Beetroot to make sure they would have success.

What could go wrong

The year is year 0 of the Tenth cycle. Patrick Parsnip takes a look at Planet Beetroot through the amazingly good telescope his Uncle Alfonso bought him for Harvest Day. He can see Beetroot are just beginning the last year of their Ninth cycle (Light takes a year to get to him). But he ‘knows’ Beetroot is really also in year 0 of it’s Tenth cycle (the universal now is with Patrick). That blasted planet Sprout can be seen too, but he tries to ignore them, their always up to something!

Patrick grabs the holy carrot, jumps in the wormhole, and appears on the surface of Beetroot, it is Year 0, he looks back at Alfafa, but something is wrong, something is very wrong.

Without anyone on Alfalfa knowing, half a year ago, Sprout had activated their ‘not a weapon’, and started moving Beetroot away at high speed.

That meant, Beetroot was only three quarters of the way through it’s final year! Not all the way through, as Patrick expected!

When the Parsnip Partnership were first hatching their plans, they had never considered this, they had arrived on Beetroot three months too early.

‘Pass the carrot’ was on; simply race to the top of mount molehill on Beetroot, and back to the vally of Lazy Bed on Alfalfa, and the crown would be his!

But… Was this cheating? When he wormholed back from Beetroot, he would arrive on Alfalfa, weeks before the race had even started!

A moving reference

If we pick a universal now, we have to choose a reference point. And that reference point needs to come with us on our story.

The sprouts

The short green ones had a plan… There was no rule against their entry… With their shorter legs, no way could they win the great race. Just as the other entrants, they wormholed to Beetroot, but were ready for the surprise, they saw Alfalfa was three months slower than expected, and jumped back straight away. They now had three months in which to sabotage Patrick of the Parsnip Partnership, before he even had a chance to race.

All hail our new green, pungent, king!

In a moving universe, Faster than Light travel and wormholes start to allow time travel backwards. Exploring the various corners of the implications of the ‘universal now’, and causality impacted by FTL, opens a nice space (ahem) for world building!

Categories
stories The Shouter Series

The Shouter (3)

Link to the first in the series here

Fu-kin legends bai. Rumours and stories flit around the school like bats. Parish priest makes an announcement; ‘We are not sure what exactly happened in the local last Friday, but we ask that we, as a…. communitee, do not pass judgment on what looks to be two young lads working hard on the science’.

Barman, half a head of hair and covered in steri-strips, ‘sure lookit, it could put this place on de map!’. A village where everyone plays or listens to music.

A car pulls up the drive, two tweed suits get out, and crunch up to ask mammy where the ‘young fellas’ are. ‘The shed’.

Dermot, Declan, Tweedie Dum, Tweedie De, are a close fit in the shed. ‘Youse boys are running a pirate station, that’s illegal’. Dermot, who reads too much; ‘Akshually, you’re meant to make a citation in pursuance to the Broadcasting act of 2009’. Dead air. Dermot often causes silence, this was nothing new.

‘We’ve ben asked to approach yez around an opportunity’, ‘a certain company has said thy have an empty electronics lab there in city west, no strings attached’. ‘No stings me hole’. Phone number swapped. shoulders shrug and ‘sure why not’. Offer accepted that night.

Declan, who knows about sound, looking forwards to getting his hands on some better equipment. Dermot, who reads a lot; ‘No strings me hole’.

Part 4 -> The Shouter (4)

Categories
stories The Shouter Series

The Shouter (2)

The Shouter – Part 1

The bus, the way home, the ignominy. Two less than happy campers, Dermot and Declan stared glumly into their box of equipment. Their new invention, “The Shouter”, looked like a coke can on it’s side, wrapped in copper wire, sitting inside a poster tube. Maybe they should have painted it to make it look more… well, fancy. That said, haey knew why no one was impressed… they weren’t allowed turn The Shouter up! They couldn’t hear it!

A mind melding, brain scratching session ensued, how to let people hear the shouter. Like, really hear it. Declan, who knows about sound, knows a local band that plays in the local pub every local Friday. Dermot, who didn’t, thinks this is a great idea.

Friday. Pub with about three locals trying to ignore the ‘young lads’ messing around with the ancient PA system. Declan wiring up two prototype ‘Shouters’. Dermot allowed play with the mixing deck trying to see how much power they could feed in. The band tuning on stage, excited. They play this gig for fun, mostly, and free pints. Everyone in this town plays music. Or listens to it.

Declan, who knows about sound, decides to hold the “Shouters” in reserve, and lets the regular sound system work away for a while. Pub fills up, rock music kicks in. Everyone TALKING VERY LOUDLY to hear each-other. Dermot; signals to bassist who signals to drummer. Singer nods and takes a break. Dermot flicks the ‘on’ switch. The lights flicker a bit. Who cares? But, there is a definite hum in the air. Declan, who knows about sound, adds a filter, adjusts some sliders, and the hum gets softer.

Dermot is excited. He has been telling anyone who would listen, and many who didn’t, about The Shouter. Bored them half to death, but the word was out (the three locals who saw the setup, decided at this point, to “maybe head out for a shmoke”, “yep, mbby down the ways a bit”).

The crowd moved up to the stage. The song was ‘Killing in the name of’, it starts with a chwoooongggggg. It would be incorrect to say the place went silent, it was late Friday in a pub, halfway up a mountain in Wicklow. But there was a ceartain palpable potential in the air. The atmosphere was electric. Dermot was a good “hype man”.

The guitarist and bassist both chwoooongggggged.

– White pain then silence. Screams but no sound. Beer, Spirits and glass blizzarding. The pub, a deranged snowglobe shook hard by a giant. People crying, blood in their noses falling and twirling as Beer and Spirits and glass flurried over them.

A beautiful ringing starting to come out of the silence as ears decided it was time to start working again.

Declan, who knew about sound, turned to Dermot, both of them with the biggest grins possible plastered across their faces. It had worked! They had Heard!

Continued here: The Shouter (3). (I’m new at making this stuff public, so comments etc are welcome!)

Categories
stories The Shouter Series

The Shouter

‘That’s like a mule kickin ya’. ‘Jasus, its makin me feel sick’.

Dermot and Declan, one time participants in the annual ‘Young scientist competition’ held every year in Dublin, Ireland; unwittingly experimenting on themselves with a new speaker design…

‘You know regular speakers, they use elastic to bounce the cone back and forth’ Dermot wondered one day while not paying attention in Maths class, or was it Physics? ‘What if we, ya know, used a metal cylinder as a driver, and used an electromagnet to drive it in and out of a box’ sketch sketch sketch.

‘It would mean we could make it move very slowly even if it was small’. Declan, who knew about sound, was sceptical to say the least, but, did admit that the requirement of having a larger cone to vibrate more slowly to produce bass notes would not be required if one could maintain control of the objects position exactly; ‘We could even focus the output’.

Experimentation proceeded in the shed out the back of Declan’s house. This also happened to be the home of “Radio Wow”, the dance orientated pirate radio station blasting the airwaves (and many nearby unprotected electrical devices) ‘Wowing you out every Monday to Thursday after homework yowsa‘. While prototyping the new ‘speaker’ (at this point they wanted to call it a ‘Shouter’) with Massive Attack’s ‘Teardrop’; had made themselves feel very uncomfortable- ‘intestines weren’t built for shaking Dermot‘.

Success achieved, the Shouter could achieve any low frequency, and up to ultrasonic. The loudness was a function of how long the central cylinder was, and how much power they put into it.

With four of them stacked in a box, they could also make the sound pulse highly directional, and more importantly, focused.

Cue the event, Dermot and Declan set up their display at the Young Scientists. Sleepless nights proceeded, dreaming of just how impressed everyone would be, not just of the ‘Shouter’ as it was officially named, but also of their amazing choice of music which which they would demo it! Declan, who knew about sound, had worked on the playlist all week. Dermot, had thought just how impressed all the female young scientists might be, and did no work at all.

They were asked to turn it down after approximately 47 seconds.

The organisers were not impressed. Dermot and Declan were not impressed. The ‘growing edible mushrooms on poop’ young scientists from the stand directly across from them were not impressed; they were also quite pungent having gotten quite the fright as ‘Whole lot of Rosie’ by ACDC accidentally focussed on them while they were in the middle of a particularly delicate part of their display setup.

To be continued….. and perhaps edited….

The Shouter (2)

Categories
Meta quick

I’m a writer Mom

I’m sitting at a table of people I mostly don’t know, and it’s gradually became clear that almost everyone here is “I work in IT”.

I try not to say “I work in IT”, fail, then try to describe what I actually do, and fail again. It doesn’t sit well with me. Hosted on AWS blah. If I said Carpenter, Architect etc etc, you might know what I do, or have an idea anyway. Shit, even “Software engineer” makes some sense.

So, my goal is to be a writer. Creating gives a good feeling, and is challenging in a different way. It’s not problem solving, it’s not fixing the world’s problems, or even understanding them; it’s creating something that, at best, is a mirror held up to the world. Maybe a funhouse mirror. I have written all my life, on and off, but have never being…. a Writer.

Listening to “slip of the keyboard” by Terry Pratchett; He always started a new book as soon as his last was finished, because if he wasn’t writing, then calling himself a writer was cheating.

So I’m flipping this over and saying as long as I’m writing…. I’m a writer.

Categories
Python

Kubernetes, moving from an entrypoint.sh to supervisord

For reasons (specifically that my kubenetes hosts have been up and down lately) I have had to harden my deploy.

First thing and the most important was to stop the graceful shutdowns of my rabbitMQ connections. I realised it would be way better to just sleep and retry on _any_ rabbitMQ connection error, particularly if rabbitMQ shut down gracefully.

Previously I was assuming that if rabbitMQ was shutting down gracefully then the whole app was.

How wrong I was, I was informed in no uncertain terms that I should be prepared for individual containers to be shut down and restarted without the whole pod getting a restart.

To that end the following changes were needed:


def getJobs():
    l.info("Running get Jobs")
    while True:
        try:
            global connection
            global channelM
            connection = pika.BlockingConnection(pika.ConnectionParameters('rabbitmq'))
            channel = connection.channel()
            channelM = connection.channel()
            channel.queue_declare(queue=myRabbitQueue)
            channel.basic_consume(queue=myRabbitQueue, auto_ack=True, on_message_callback=callback)
            l.info("Will now continue to run")
            channel.start_consuming()
        # Don't recover if connection was closed by broker
        except pika.exceptions.ConnectionClosedByBroker:
            l.error('Rabbit error connection closed by broker')
            break
        # Don't recover on channel errors
        except pika.exceptions.AMQPChannelError:
            l.error('Rabbit error channel error')
            break
        # Recover on all other connection errors
        except pika.exceptions.AMQPConnectionError:
            l.error('Retrying rabbitMQ listener')
            continue

to

def getJobs():
    l.info("Running get Jobs")
    while True:
        try:
            global connection
            global channelM
            connection = pika.BlockingConnection(pika.ConnectionParameters('rabbitmq'))
            channel = connection.channel()
            channelM = connection.channel()
            channel.queue_declare(queue=myRabbitQueue)
            channel.basic_consume(queue=myRabbitQueue, auto_ack=True, on_message_callback=callback)
            l.info("Will now continue to run")
            channel.start_consuming()
        # Recover on all other connection errors
        except pika.exceptions.AMQPConnectionError:
            l.error('Retrying rabbitMQ listener')
            continue
        except Exception as err:
            l.error(f'Error in connecting to rabbitmq, going to retry: {err}')
            sleep(5)

Note the removal of the “# Don't recover on channel errors” where it breaks. The Break broke the whole dam run loop!

And this brought me to my next problem. My app just wasn’t shutting down cleanly. After much messing I realised that the entrypoint.sh script (it had a few “wait-for-its” then started and backgrounded my various python modules) was not passing SIGTERM, so my app wasn’t shutting down properly at all.

Because of how it was built, this never mattered, but it always took the 60 seconds to destroy when I was pushing a new version… and it was a bit annoying to have it “not be workin proper” as they say.

So I am moving to supervisord. But if there’s one this I dislike it’s config files. So let me present a “translator” from entrypoint.sh to a supervisord conf file. It’s not perfect, but it beats writing it by hand. I hope someone else finds it useful.

What is confusing to me however, is it always seems so hard do just get simple best practices in deploying a simple-ish python app to kubernetes. I thought the whole point was to make it easier for developers. If I was running my app in a VM I wouldn’t have to care about any of this stuff!

I think the reason for this is I wrote the python app from scratch, and didn’t use a framework that had all the default configs ready to go!

Here’s the helper, I hope it helps:

def generate_supervisord_conf(entrypoint_file):    
    supervisord_conf = "[supervisord]\n"
    supervisord_conf += "nodaemon=true\n"
    supervisord_conf += "logfile=/dev/null\n"
    supervisord_conf += "logfile_maxbytes=0\n"
    supervisord_conf += "user=root\n\n"
    
    programs = []
    with open(entrypoint_file, "r") as f:
        lines = f.readlines()
        for line in lines:
            if line.startswith("pipenv run"):                                                                                                                                                                                                
                program_name = line.split(" ")[2].rstrip("\n").split("/")[-1].split(".")[0]    
                programs.append(program_name)    
        
    for program in programs:    
        program_conf = f"[program:{program}]\n"    
        program_conf += f"command=/usr/local/bin/pipenv run /app/{program}.py\n"    
        program_conf += "autostart=true\n"
        program_conf += "redirect_stderr=true\n"
        program_conf += "stdout_logfile=/dev/fd/1\n"
        program_conf += "stdout_logfile_maxbytes=0\n"
        #program_conf += "depends_on=is_it_up\n" # This is the wait-for-it script
        program_conf += "autorestart=true\n\n"    
        supervisord_conf += program_conf    
        
    return supervisord_conf    
    
    
entrypoint_file = "./entrypoint.sh"    
supervisord_conf = generate_supervisord_conf(entrypoint_file)    
    
with open("supervisord.conf", "w") as f:    
    f.write(supervisord_conf)    
    

I find myself liking programmatic generation more and more!

UPDATE! I forgot about the annoying logging problems when using supervisord… please see https://docs.docker.com/config/containers/multi-service_container/ I have updated the code above

Categories
personal quick

Improve your Zoom

Just a quick note, try playing some music in the background next time if you are in a zoom meeting (or teams or whatever). You can usually adjust the volume down low compared to the zoom audio. People on the call can’t here it on your headset, and it can really make the meeting nicer.

I like a bit of chill electro to add a bit of background noise. Try a cinematic score to liven up a boring meeting a bit 🙂
eg. https://www.youtube.com/watch?v=HC9ULm4HquU

Categories
Python

Reducing boilerplate with RabbitMQ and Python

Following on from my last post about sending Rabbitmq messages with shared code in python (caveat this is not for >100 message per second requirements).

Here is how to listen to a queue (and use it), with a reduced amount of boilerplate.

I also learned you can pass a function to an imported module to get that module to “callback” to the parent… to the code!!

This is the shared code (that lives in a .py file and is imported as from blah.py import *

#TheLawsandOrdinancesoftheCitiesAnkhandMorpork.py

def getJobs(officer, callback):
    l.info(f'Waiting for jobs for {officer}')
    while True:
        try:
            with pika.BlockingConnection(pika.ConnectionParameters('rabbitmq')) as connection:
                connection = pika.BlockingConnection(pika.ConnectionParameters('rabbitmq'))
                channel = connection.channel()
                channel.queue_declare(queue=officer)
                channel.basic_consume(queue=officer, auto_ack=True, on_message_callback=callback)
                l.info(f'{officer} reporting for duty sir')
                channel.start_consuming()
        # Don't recover if connection was closed by broker
        except pika.exceptions.ConnectionClosedByBroker:
            l.error('Rabbit error connection closed by broker')
            break
        # Don't recover on channel errors
        except pika.exceptions.AMQPChannelError:
            l.error('Rabbit error channel error')
            break
        # Recover on all other connection errors
        except pika.exceptions.AMQPConnectionError:
            l.error('Retrying rabbitMQ listener')
            continue

This ^^^ stuff was boilerplate in my last app, now I can reuse the code with the following… in the actual running app:

#Detritus.py
from TheLawsandOrdinancesoftheCitiesAnkhandMorpork import *

def callback(ch, method, properties, body):
    patrol = body.decode()                 
    print(f'I have received {patrol}')     

#Then from main() just call the shared code
main():
    officer = 'Detritus'
    getJobs(officer, callback)
    #This will then live in a while loop and "callback" to the supplied callback function. All you need then is a bit of error handling

# Standard boilerplate to call the main() function to begin
# the program.
if __name__ == '__main__':
    try:
        main()
    except KeyboardInterrupt:
        print('Keyboard inturrupt')
        l.warning("Keyboard inturrupt")
        try:
            connection.close()
            sys.exit(0)
        except SystemExit:
            os._exit(0)

Again I hope the above formatting comes out well. I’m not sure if this is ok for high volume stuff, but for what I am doing (cheap parallelisation and using a messaging programming paradigm) it works good for me!

Categories
Python

Using RabbitMQ (pika) with Python

I have struggled finding what I would consider a nice way to connect to Rabbit MQ from a python program.

Some issues I have found that slack overflow answers are not great if you are reusing connections or have something that isn’t just a single sending program.

My use case, where I am programming around a narrative (in this new project I am using “The Watch” from Terry Pratchett’s Discworld.

In my last project I had what amounted to boiler plate code in each “Character” (python app). For this new project (the Quantum one), I wanted something a bit easier and cleaner.

So let me introduce TheLawsandOrdinancesoftheCitiesAnkhandMorpork.py

This is a “helper” module that I will import * from. This is how I wrote the messaging side. This produces less crap in the Rabbit MQ logs than calling a channel.close() also:

import pika
import json
import logging as l
exchange = ''

def sendMessage(person, patrol):                                                           
    try:                                                                                   
        patrol = json.dumps(patrol)                                                        
    except Exception as err:                                                               
        l.error(f'could not dump the patrol to a json')                                    
    try:                                                                                   
        with pika.BlockingConnection(pika.ConnectionParameters('rabbitmq')) as connection: 
            #connection = pika.BlockingConnection(pika.ConnectionParameters('rabbitmq'))   
            channelM = connection.channel()                                                
            channelM.queue_declare(queue=person)                                           
            channelM.basic_publish(exchange=exchange, routing_key=person, body=patrol)     
    except Exception as err:                                                               
        l.error(f'Problem sending rabbit message: {err}')                                  

On my screen that is a bit hard to read;

What I am doing is a function that takes the name of a “character” (ie. a queue) and a dict. I then encode this as a JSON, and using the “with” block, send it to the correct queue.

By avoiding the connection.close() call I no longer get and error in rabbitMQ saying connection closed unexpectedly.

It may not be the most efficient, not reusing an existing connection. But the connection bringup is tiny, and I would rather take cleanliness over efficiency in this case.

I will be running quantum simulations so the bottleneck will not be here!

Categories
personal quick stories

Quick story

Driving along a winding road, up the side of a hill.
It is deepening dusk, and the road curves upwards to the right.
The mountain side has some trees (pines) and short grass. It’s cold, maybe close to freezing.
The car is cold, the windscreen is still a small bit fogged.

The surface of the road changes to closely packed upturned feet, with little faces on the sole (just below the toes). They are all staring at you without speaking, as your tires loose grip on the shiny upturned flesh. Your car skids, careens across the road, and out over the edge of the abyss.

As the car starts tipping end over end, rapidly approaching the ground, all you can think of is the road made of upturned feet.