Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
epswing
Nov 4, 2003

Soiled Meat
Thanks for the feedback so far.

Mr Shiny Pants posted:

What a user does should not cause an exception on your server and the right handling should be in place.
I would not use exceptions for this, crappy input is not exceptional. :)

At least, that is how I try to write my code.

Let's say it's not an input validation problem. The user tries to execute a command that, it turns out, shouldn't be executed because of some business logic reason. My controllers are generally thin and just call some service method. Somewhere in the service, an exception is thrown (e.g. "You can't delete X because of Y"), and eventually the user sees the message of that exception.

Where else would be the right handling for this scenario?

ThePeavstenator posted:

Use Application Insights if you're using .NET and especially if you're using .NET and hosting on Azure. Gives you a ton of metrics right out of the box with no configuration and is very customizable.

I'll check this out, thanks.

ThePeavstenator posted:

You shouldn't be exposing these through your web API. It can be a security list because that stack trace could potentially include things like query strings or worse, configuration information. Even if you're careful to only throw certain exceptions and it's internal use only, you've now coupled the consumers of your API to C# stack traces that are thrown by .NET Core default HTTP error responses. Ideally you're writing web APIs so that if you wanted to, you could rewrite them in a completely different framework/language and not break compatibility with existing consumers. Older ASP.NET projects don't even throw the same errors, they return full error HTML pages or XML in the response.

Sorry, I should have included more context. I'm using WebAPI basically for RPC. (Years ago this was all WCF.) The client is an internal WPF app. I never even deal with json, as ApiController and HttpClient take care of all the serializing/deserializing. So, while I agree with you that in general I shouldn't be exposing certain data, and shouldn't be coupling my API to C# responses, in my case I think it's acceptable because I control both the server and the clients.

ThePeavstenator posted:

You don't need to throw an exception if you're returning a response right from the controller. The way I usually break down responsibility of each layers in your typical web service is with the controller having 2 responsibilities: validate incoming request parameters/headers/whatever, and then respond with an appropriate response code from the result it receives from the service layer. If you're validating input in the controller, you can just return BadRequest() without throwing an exception if the inputs are not valid. You shouldn't be using exceptions for controlling execution flow in general.

ThePeavstenator posted:

What you should do is return a standard message with just enough information to tell the consumers what the problem is. It could be as simple as a static string, or as verbose as a JSON blob with a bunch of descriptive status fields.

The client POST might fail for several reasons, and should react differently based on which reason was given. I don't particularly want to check the verbose message I show the user (if (responseMessage == "Error: Unable to compute because X") { ... }). I could include an explicit internal error code in the response, and the client would then check if (responseCode == ErrorCodes.FAIL_X) { ... }. I was thinking somewhere between those two might be to throw an exception, and use the exception type, leading the client to check if (responseExceptionType == typeof(MyXException).ToString()) { ... }. If using the latter method, my service could e.g. throw new MyXException() or MyYException() and the client would get a 400, an exception message to show the user, and an exception type to act upon.

The bottom line is the consumer needs to act differently based on why their request failed. Is throwing an exception in a service, letting a controller package that up for the client, and having the client decide what to do based on the type of exception thrown a major no-no (given that I control the server and clients)?

epswing fucked around with this message at 07:46 on Jan 6, 2019

Adbot
ADBOT LOVES YOU

epswing
Nov 4, 2003

Soiled Meat

ThePeavstenator posted:

You shouldn't be using exceptions for controlling execution flow in general.
I re-read and this struck me as odd. What's the point then of being able to catch specific exceptions?
C# code:
try { /* try something */ }
catch (ExceptionA) { /* do something */ }
catch (ExceptionB) { /* do something else */ }

EssOEss
Oct 23, 2006
128-bit approved
The advice you are getting is for how to design a REST API, because that is what people most often do with Web API. From your mention of RPC however, I see that you actually have nothing like a REST API here.

Thus what you effectively have is a custom protocol that just happens to be based on HTTP on some layer. Do not expect any standard web API design guidelines to apply to your situation - this is not how people generally create web APIs at all.

That being said, we can take a comparison with gRPC, Google's state of the art RPC API. It does not expose any information beyond its equivalent of "500 Internal Server Error" when an exception occurs. They probably know what they are doing, so follow suite. What I do in my gRPC APIs when I want the client to differentiate error types is that I include an ErrorCode in my response. My response types look like:

code:
class DingleTheDangleResult
{
    DingleErrorCode Error; // If failure
    DingledDangle Result; // If success
}
Seems to work OK so far for RPC style usage. Yes, this means from the gRPC library perspective, a call that resulted in an error is actually a successful call (it returns the result type just fine, it simply has different fields filled).

ThePeavstenator
Dec 18, 2012

:burger::burger::burger::burger::burger:

Establish the Buns

:burger::burger::burger::burger::burger:

epalm posted:

I re-read and this struck me as odd. What's the point then of being able to catch specific exceptions?
C# code:
try { /* try something */ }
catch (ExceptionA) { /* do something */ }
catch (ExceptionB) { /* do something else */ }

Let's take this example you posted:

epalm posted:

C# code:
public class MyController : ApiController
{    
    [HttpPost]
    public void Bar()
    {
        try
        {
            throw new Exception();
        }
        catch (Exception ex)
        {
            log.Error(ex);
            throw ResponseException(Request, ex);
        }
    }
}

I assume this is a minimal example and there's more in that try block in your actual code, but basically what the "throw new Exception();" does in this example is act as an expensive goto statement.

If you're throwing an exception, the code you're writing should either reach a condition that it doesn't know how to handle, or is beyond the scope of what it should handle and needs something up the call stack to deal with it. As an example from the .NET Framework source code:
C# code:
public class TcpClient : IDisposable {

    /* Snipped code */

    public void Connect(string hostname, int port) {
        /* Snipped code */

        if ( m_Active ) {
            throw new SocketException(SocketError.IsConnected);
        }

        /* Snipped code */
    }

    /* Snipped code */
}
TcpClient doesn't even bother to try and deal with the situation where it's trying to connect to a socket that's already been connected to. Instead it throws it to the caller. Maybe TcpClient could just silently continue and just use the already connected socket, but not every caller will want this to invisibly succeed.

If you're the caller (or a caller further up the stack), you can choose to handle this condition because how it should be handled is unambiguous for your use case. For example:
C# code:
public class TcpWrapperThatJustWantsAnOpenClient {
    private TcpClient client;
    public TcpWrapperThatJustWantsAnOpenClient (TcpClient client) {
        this.client = client;
        try {
            this.client.Connect()
        }
        catch (SocketException se) {
            Console.WriteLine("Got a SocketException when connecting the client in the constructor, but I know what I want to do in this situation.");
        }
    }
}
If you know what you want to do with an exception you're throwing, then don't throw it and just do the thing. That's what people mean when they say don't use exceptions as control flow. Exceptions are meant to be thrown up the call stack until they either crash the program, or reach a caller that knows how they want to handle it.

So to take your code and remove the exception performing control flow:
C# code:
public class MyController : ApiController
{    
    [HttpPost]
    public void Bar()
    {
        /* Rest of Your Code */

        if (badShitHappened) {
            var exceptionString = $"Here's some bad poo poo info: {badShitInfoString}";
            log.Error(exceptionString);
            throw ResponseException(Request, exceptionString);
        }

        /* More Code */
    }
}
Now you're checking if an exceptional condition you don't want to handle occured, and then you throw it to the caller (which in this case is the ASP.NET framework).

ThePeavstenator fucked around with this message at 08:51 on Jan 6, 2019

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

downout posted:

Anyone have some good recommended reading regarding DI? I've used it in various settings, but it was always more from a format of "this is how we do it, what we use, just keep doing it that way". It was never covered in my formal education (and mostly abstracted away by libraries in my post-education experience), so I think it might be really helpful to see a more formal usage/construction in real world scenarios.
For dependency injection itself:
Dependency injection demystified. Read that first and maybe if you're feeling adventurous, the stuff he links to at the end of the post.

For an example of how to set it up in a project (this uses simple injector, there other other DI frameworks like autofac, and asp .NET core has a DI framework build in)
Simple injector quickstart

The two links give like 95% of what you need to know to understand DI and DI Containers.

Bruegels Fuckbooks fucked around with this message at 08:57 on Jan 6, 2019

Mr Shiny Pants
Nov 12, 2012

epalm posted:

Thanks for the feedback so far.


Let's say it's not an input validation problem. The user tries to execute a command that, it turns out, shouldn't be executed because of some business logic reason. My controllers are generally thin and just call some service method. Somewhere in the service, an exception is thrown (e.g. "You can't delete X because of Y"), and eventually the user sees the message of that exception.

Where else would be the right handling for this scenario?


Well if you control both the server and the client, it is not exactly user facing, the only consumer is a WPF application and it won't become an API endpoint in the future for other applications: it depends. :)

Going from the above explanation: If an exception occurs in the service layer you probably know why it happened, why not handle it in your controllers?

B-Nasty
May 25, 2005

Bruegels Fuckbooks posted:

For an example of how to set it up in a project (this uses simple injector, there other other DI frameworks like autofac, and asp .NET core has a DI framework build in)
Simple injector quickstart

Exactly what I was going to post.

The entire Simple Injector docs site is easily one of the best software doc/wiki resources I've ever seen. Even if you don't care about DI, read this guide to learn how technical documentation should be written. Another example would be the Postgres docs. Again, even if you don't use Postgres, it's like a full RDBMS/SQL training course.

I actually use StructureMap for my container, partially due to inertia and partially due to its convention-based auto-registration, but SimpleInjector would be my choice if I was starting fresh.

brap
Aug 23, 2004

Grimey Drawer

B-Nasty posted:

Ugh. So what do you do when, as is typical in the real world, Foo has 5 dependencies all of which have multiple dependencies themselves, ad infinitum? I prefer not to manage my dependency tree myself - we have containers that do that for us. I'd much rather change RealBar to BetaRealBar in one spot than have to dig all around the codebase to find where I new'd up a bunch of hard-coded dependencies.

Foo’s default constructor will provide the “prod” dependencies (repeat transitively) and the mock IBar used in testing just returns hard coded results so it doesn’t need the RealBar dependencies specified. Am I missing something?

B-Nasty
May 25, 2005

brap posted:

Foo’s default constructor will provide the “prod” dependencies (repeat transitively) and the mock IBar used in testing just returns hard coded results so it doesn’t need the RealBar dependencies specified. Am I missing something?

I didn't communicate it well, but I was referring more to common (repeated) dependencies. If you had many classes that took a dependency on, say, ILogger and they all were responsible for constructing FooLogger, changing that everywhere you manually wired up the instance would be a pain.

Not to mention that containers (subject to how they are configured) won't construct a zillion instances of FooLogger for every ILogger dependency in a given 'request'; they'll create one and share it. See StructureMap's 'Transient' lifecycle: http://structuremap.github.io/object-lifecycle/supported-lifecycles/

Cuntpunch
Oct 3, 2003

A monkey in a long line of kings
Well this is going to be a rather flip-flop post on DI:

On one hand, I wanted to note that while I can see the benefit of offering a default constructor with the production implementation included, my experience with it has been that in larger projects it can create a tricky situation where you end up needing to constantly be on-guard for misuse. And by that I mean:

code:
public class Foo : IFoo
{
	public Foo(IBar bar){}
	public Foo() : this(new Bar()) {}
}

public class ThingDoer
{
	public ThingDoer(){} //Injection is a pain in the rear end, or I didn't realize I needed an IFoo

	public void SomeOtherThing()
	{
		//Oh hey I need a Foo
		var newFoo = new Foo();
	}
}
And yes it can be untangled if caught early, but if not, then you suddenly have a cascade of 'test fails or is too hard to write' or if this is part of a new feature, now there's three or four classes that need to be fixed. It gets kind of crazy kind of quickly.



But on the other hand, I guess I'm curious about how best to handle DI at a scalable sense. Using IOC containers as service locators has (mostly) felt a bit ugly to me. But at the same point, having to pass around dependencies manually especially when dealing with deeper object graphs, seems to get kind of hairy as well. The examples and quickstarts are always too simple to see the picture at scale. Consider the SimpleInjector quickstart: Ok, an CancelOrderHandler. But that's captured in Main() - and it doesn't necessarily make sense to me to also have an VerifyOrderHandler, ConfirmOrderHandler, OrderPaymentHandler, RefundOrderHandler, CreateOrderHandler, and all the other various domain objects in a quick 'ok just grab it off a global container' sense, especially in Main. So what, then?

B-Nasty
May 25, 2005

Cuntpunch posted:

But on the other hand, I guess I'm curious about how best to handle DI at a scalable sense. Using IOC containers as service locators has (mostly) felt a bit ugly to me. But at the same point, having to pass around dependencies manually especially when dealing with deeper object graphs, seems to get kind of hairy as well. The examples and quickstarts are always too simple to see the picture at scale. Consider the SimpleInjector quickstart: Ok, an CancelOrderHandler. But that's captured in Main() - and it doesn't necessarily make sense to me to also have an VerifyOrderHandler, ConfirmOrderHandler, OrderPaymentHandler, RefundOrderHandler, CreateOrderHandler, and all the other various domain objects in a quick 'ok just grab it off a global container' sense, especially in Main. So what, then?

Maybe I'm not following you, but there should only ever be one place where you grab a service directly from the container. For a web application, this would be when the controller being hit is instantiated or in a console app once in Main. In the web case, before Core, there was some boilerplate you had to add to the project that would tap into ASP.Net internals to resolve controllers from the container, after that, everything is injected in the constructors. With Core, that's all built in, and you can use the default service locator or plug in one of the 'aftermarket' ones.

In your example, you'd want to have a highest-level OrderDoer that has all of those other handlers as dependencies. Then, in Main, you'd have one service location from the container that resolves OrderDoer and all the dependencies below it.

raminasi
Jan 25, 2005

a last drink with no ice

New Yorp New Yorp posted:

code:
public RealBar(IBaz baz) { ... }
public RealBar() : this(new RealBaz()) {}

public RealBaz(IQux qux, IQaz qaz) {...}
public RealBaz() : this(new RealQux(), new RealQaz()) {}

public RealQux(IThinkYouGetTheIdea ) ....
The dependency chain is self-constructing. There's an assumption here (which, to be fair, isn't always the case) that there's a single "real" implementation and any other implementations are for testing purposes, as opposed to something that is truly using an interface to allow for multiple implementations.

What do you do if you have two different types that depend on IBaz and they need to use the same one?

Cuntpunch
Oct 3, 2003

A monkey in a long line of kings

B-Nasty posted:

Maybe I'm not following you, but there should only ever be one place where you grab a service directly from the container. For a web application, this would be when the controller being hit is instantiated or in a console app once in Main. In the web case, before Core, there was some boilerplate you had to add to the project that would tap into ASP.Net internals to resolve controllers from the container, after that, everything is injected in the constructors. With Core, that's all built in, and you can use the default service locator or plug in one of the 'aftermarket' ones.

In your example, you'd want to have a highest-level OrderDoer that has all of those other handlers as dependencies. Then, in Main, you'd have one service location from the container that resolves OrderDoer and all the dependencies below it.

So to some degree I'm thinking less in ASP terms and more in standard app model terms. And I am likely just somehow blurring in my head the logic of doing stuff manually with doing stuff via an IOC container building the graph at startup. But I think the question starts to become having classes that involve multiple layers of dependencies. Trying to think through the 'register everything, then just resolve 'the root class' - doesn't that end up in a hypothetical root class with huge injection footprint? In a hypothetical inventory management system, for example, your main() would want an order management service, an inventory status service, a user management service, etc etc. And if each of those involves their own data-access dependencies, for example, do you just accept that this root class will have (n) dependencies injected, and for each of those dependencies you just let the IOC container sort it out? But if a single layer here ends up with a bit of a monolithic dependency situation(say 5-6 injected args), then is that just an architecture smell of 'go back and find the abstraction layer you're missing'?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

raminasi posted:

What do you do if you have two different types that depend on IBaz and they need to use the same one?

Needing to maintain a long-lived instance that's shared between multiple users makes me twitchy because it starts to smell like a singleton, so the lovely answer is "don't do that in the first place". I understand that this may be unavoidable if, say, you have a very-expensive-to-construct object.

The real answer is that you either use an IoC container that manages this for you, or fall back to the trusty factory pattern.

Bruegels Fuckbooks
Sep 14, 2004

Now, listen - I know the two of you are very different from each other in a lot of ways, but you have to understand that as far as Grandpa's concerned, you're both pieces of shit! Yeah. I can prove it mathematically.

Cuntpunch posted:

So to some degree I'm thinking less in ASP terms and more in standard app model terms. And I am likely just somehow blurring in my head the logic of doing stuff manually with doing stuff via an IOC container building the graph at startup. But I think the question starts to become having classes that involve multiple layers of dependencies. Trying to think through the 'register everything, then just resolve 'the root class' - doesn't that end up in a hypothetical root class with huge injection footprint? In a hypothetical inventory management system, for example, your main() would want an order management service, an inventory status service, a user management service, etc etc. And if each of those involves their own data-access dependencies, for example, do you just accept that this root class will have (n) dependencies injected, and for each of those dependencies you just let the IOC container sort it out? But if a single layer here ends up with a bit of a monolithic dependency situation(say 5-6 injected args), then is that just an architecture smell of 'go back and find the abstraction layer you're missing'?

One of the good things about using a DI container is that your root class ends up being the DI container itself - you're avoiding having to write a custom XXXManager class that initializes everything.

B-Nasty
May 25, 2005

Cuntpunch posted:

Trying to think through the 'register everything, then just resolve 'the root class' - doesn't that end up in a hypothetical root class with huge injection footprint? In a hypothetical inventory management system, for example, your main() would want an order management service, an inventory status service, a user management service, etc etc. And if each of those involves their own data-access dependencies, for example, do you just accept that this root class will have (n) dependencies injected, and for each of those dependencies you just let the IOC container sort it out?

You might be overthinking it. How would you do it without a container? You probably wouldn't have your Main method new-ing a bunch of stuff; you'd have it new a something which new-s another couple things and those...and so on.

If you had an entry point that was driven by a queue with a bunch of different queue message task types, for example, you may want to request specific handlers from the container depending on the message, but that's more of an advanced approach.

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!
Now that my hobby site is Capital F Finished, I am going to look into one of two things:

1) Look into alternative hosting sites besides AWS for my .net core projects.
2) Write me some Vue.js

As far as 1) goes, what is everyone's preferred docker cloud service hosting PaaS VM container <more bullshit words> here place they deploy hobby code to? So far I've come across Heroku, Digital Ocean, Pivotal, and then the big ones, AWS and Azure. I never hear anything about Googles platforms for some reason.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

User0015 posted:

Now that my hobby site is Capital F Finished, I am going to look into one of two things:

1) Look into alternative hosting sites besides AWS for my .net core projects.
2) Write me some Vue.js

As far as 1) goes, what is everyone's preferred docker cloud service hosting PaaS VM container <more bullshit words> here place they deploy hobby code to? So far I've come across Heroku, Digital Ocean, Pivotal, and then the big ones, AWS and Azure. I never hear anything about Googles platforms for some reason.

I like Azure, but I also work for a Microsoft partner and do a lot of work in Azure, so I'm biased.

mst4k
Apr 18, 2003

budlitemolaram

User0015 posted:

]Digital Ocean

Congrats! I use Linode to host my SaaS app. I'm going to move to Azure .... soon.... someday.

A $10 linode box goes a really long way though, lol.

EssOEss
Oct 23, 2006
128-bit approved
I have used Azure for VM hosting (and other stuff) for years and it is okay. The automation has royally sucked, though - they invented their own JSON template based "language" that is nearly incomprehensible to humans and trying to get something automatically created is an exercise in frustration trying to get their "templates" to do the right thing.

I think they are now up to 3 versions of their PowerShell commands for using Azure, each incompatible with the other. And with fun situations like "why does this 0.3 second API call take 600 seconds if I do it via the Azure PowerShell commands?"

But for a hobby site where you are not automating multi-tier deployments and can live with just the (reasonably okay) web portal, it is probably golden.

Note that for a simple web app, you might be better off with an Azure Web App (basically an oldschool webserver managed by Azure). It does not give you a full VM but gives you a webserver. Maybe have an easier life managing it, plus you can stuff multiple sites onto the same webserver at no extra cost.

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!

EssOEss posted:


Note that for a simple web app, you might be better off with an Azure Web App (basically an oldschool webserver managed by Azure). It does not give you a full VM but gives you a webserver. Maybe have an easier life managing it, plus you can stuff multiple sites onto the same webserver at no extra cost.

Considering the amount of bullshit I've had to put up with, I'd almost prefer having nothing but an open box to do as I'd like. gently caress it, I'll spin up my own nginx server. It's probably easier than some of the crap I've had to deal with recently.

Cuntpunch
Oct 3, 2003

A monkey in a long line of kings

B-Nasty posted:

You might be overthinking it. How would you do it without a container? You probably wouldn't have your Main method new-ing a bunch of stuff; you'd have it new a something which new-s another couple things and those...and so on.

If you had an entry point that was driven by a queue with a bunch of different queue message task types, for example, you may want to request specific handlers from the container depending on the message, but that's more of an advanced approach.

Yeah I think that's just it - I'm overthinking it a bit, and getting a little confused by the inversion. I've spent my entire professional career working in projects where IOC was either completely absent or horribly irregularly implemented, so I've just not got hands-on experience with a large codebase which handles it 'well'.

Thanks for setting my head straight :v:

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!

EssOEss posted:

I have used Azure for VM hosting (and other stuff) for years and it is okay. The automation has royally sucked, though - they invented their own JSON template based "language" that is nearly incomprehensible to humans and trying to get something automatically created is an exercise in frustration trying to get their "templates" to do the right thing.

I think they are now up to 3 versions of their PowerShell commands for using Azure, each incompatible with the other. And with fun situations like "why does this 0.3 second API call take 600 seconds if I do it via the Azure PowerShell commands?"

But for a hobby site where you are not automating multi-tier deployments and can live with just the (reasonably okay) web portal, it is probably golden.

Note that for a simple web app, you might be better off with an Azure Web App (basically an oldschool webserver managed by Azure). It does not give you a full VM but gives you a webserver. Maybe have an easier life managing it, plus you can stuff multiple sites onto the same webserver at no extra cost.


New Yorp New Yorp posted:

I like Azure, but I also work for a Microsoft partner and do a lot of work in Azure, so I'm biased.

Since you both are familiar with Azure, let me ask you a few questions.

Is there a good write up on spinning up your own sites on Azure, that also are cheap? Right now, the way I keep costs down on AWS annoys me because I have to deploy to three different areas to get things to work. AWS feels like it was designed with bigger businesses in mind. As it stands, a single EC2 instance is about $12 a month on their smallest size, and a SQL server about the same. $24 to run a website? Uh no thanks.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

User0015 posted:

Since you both are familiar with Azure, let me ask you a few questions.

Is there a good write up on spinning up your own sites on Azure, that also are cheap? Right now, the way I keep costs down on AWS annoys me because I have to deploy to three different areas to get things to work. AWS feels like it was designed with bigger businesses in mind. As it stands, a single EC2 instance is about $12 a month on their smallest size, and a SQL server about the same. $24 to run a website? Uh no thanks.

I'm running a low-volume site, static on Azure at the lowest tier that supports custom domains and SSL. It's about $20 a month. Azure has a free tier, too, which is free, but doesn't support SSL/custom domains.

Look at the pricing calculator: https://azure.microsoft.com/en-us/pricing/calculator/

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!
20 a month just seems high to me. And static files only? No database?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

User0015 posted:

20 a month just seems high to me. And static files only? No database?

Correct. It's a site for my wedding. Super simple, straight HTML/CSS/JS.

If I didn't need a domain or want SSL, I could use the free tier, which is, well, free.

Just a domain, about $10.

I get $150 / month of free Azure, though, so I'm fine with "paying" for it.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

If it doesn't get many hits, you can host static sites on Azure Functions, pay literal cents, and get free custom domain support and SSL.

https://thinkbeforecoding.com/post/2018/12/07/full-fsharp-blog
https://thinkbeforecoding.com/post/2018/12/09/full-fsharp-blog-2

Skip all the stuff about actually generating the HTML and this sounds like your use case.

quote:

Azure functions is a FaaS platform, but we'll write no code for it. Using consumption plan, we'll pay only for used resource:

blob storage to store posts and functions definitions: currently €0.0166/GB/month in West Europe region
Read operations: €0.0037/10.000reads/month
Write (when uploading and some logs): €0.0456/10000writes/month
in my case, I get 0.01€ for reads and 0.01€ for writes... you mileage may vary depending on the trafic on your site.

Functions provide custom domain support for free, and you can install your own SSL certificate.

Drastic Actions
Apr 7, 2009

FUCK YOU!
GET PUMPED!
Nap Ghost

New Yorp New Yorp posted:

Correct. It's a site for my wedding. Super simple, straight HTML/CSS/JS.

If I didn't need a domain or want SSL, I could use the free tier, which is, well, free.

Just a domain, about $10.

I get $150 / month of free Azure, though, so I'm fine with "paying" for it.

I'm not sure if it works with the free tier, but you can get Let's Encrypt to work with App Services and Functions, which takes care of the SSL for ya. It's kind of a pain to set up the first time, but do it once and it's super simple for every other site you want to handle.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Drastic Actions posted:

I'm not sure if it works with the free tier, but you can get Let's Encrypt to work with App Services and Functions, which takes care of the SSL for ya. It's kind of a pain to set up the first time, but do it once and it's super simple for every other site you want to handle.

I did exactly that! :)

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!

NihilCredo posted:

If it doesn't get many hits, you can host static sites on Azure Functions, pay literal cents, and get free custom domain support and SSL.

https://thinkbeforecoding.com/post/2018/12/07/full-fsharp-blog
https://thinkbeforecoding.com/post/2018/12/09/full-fsharp-blog-2

Skip all the stuff about actually generating the HTML and this sounds like your use case.

It's the opposite for me. Setting up AWS' S3 buckets for static files is also pretty simple, and just as cheap.

My question is when you need to start involving DB's and middle tier api's, prices start jumping into the $20+ range. That's when I got curious and wondered if there's any hosting out there where I could either host things for cheap, or if I could get my hands on my own box for like 5$ and set it all up myself.

Volguus
Mar 3, 2009

User0015 posted:

It's the opposite for me. Setting up AWS' S3 buckets for static files is also pretty simple, and just as cheap.

My question is when you need to start involving DB's and middle tier api's, prices start jumping into the $20+ range. That's when I got curious and wondered if there's any hosting out there where I could either host things for cheap, or if I could get my hands on my own box for like 5$ and set it all up myself.

DigitalOcean, Linode and others have a virtual machine available for $5/month. you can put whatever you want in it. I have one in Digital Ocean with postgresql and 3 services running and some dumb website and is working just fine. Sure it cannot handle a gazillion users per day, but meh ...

I'm not familiar with the AWS pricing, but surely it cannot be a lot worse for that level of a machine.

sadus
Apr 5, 2004

Whatever you use, don't forget backups though, cheap and even expensive things sometimes go poof

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!

Volguus posted:

DigitalOcean, Linode and others have a virtual machine available for $5/month. you can put whatever you want in it. I have one in Digital Ocean with postgresql and 3 services running and some dumb website and is working just fine. Sure it cannot handle a gazillion users per day, but meh ...

I'm not familiar with the AWS pricing, but surely it cannot be a lot worse for that level of a machine.

An EBS micro + SQL DB runs every hour for the month, so the costs quickly add up.

I've tried moving code over to their Lambda/Serverless Aurora setup, but that becomes a pain in the rear end to diagnose and debug issues. I'd rather just have a box. And yeah, I'm toying around with DigitalOcean right now, and trying out their dokku setup for fun.

epswing
Nov 4, 2003

Soiled Meat

ThePeavstenator posted:

I assume this is a minimal example and there's more in that try block in your actual code, but basically what the "throw new Exception();" does in this example is act as an expensive goto statement.

Oh, the example I posted was just an analog for something further down the call stack throwing an exception. I wouldn't actually throw an exception there.

NihilCredo
Jun 6, 2011

iram omni possibili modo preme:
plus una illa te diffamabit, quam multæ virtutes commendabunt

If you're trying to run a database on a few dollars a month, you can almost definitely use SQLite instead of PostgreSQL or whatever.

Means you don't need to look for database hosting services at all, since the "DB" is just a static resource file, and you can just run your webapp on some kind of managed service, like a FaaS where you only pay for actual use.

Even if you prefer to run on a cheap minimum-tier VM and could install postgres, SQLite will eat less of the 512MB RAM or whatever you get from your provider.

User0015
Nov 24, 2007

Please don't talk about your sexuality unless it serves the ~narrative~!

NihilCredo posted:

If you're trying to run a database on a few dollars a month, you can almost definitely use SQLite instead of PostgreSQL or whatever.

Means you don't need to look for database hosting services at all, since the "DB" is just a static resource file, and you can just run your webapp on some kind of managed service, like a FaaS where you only pay for actual use.

Even if you prefer to run on a cheap minimum-tier VM and could install postgres, SQLite will eat less of the 512MB RAM or whatever you get from your provider.

That's where aws gets you. Their ec2 instances specifically lock down sqlite, so you run into a host of permission and access issues trying to get an app to open it. Smart for them, but it's really soured me obviously.

Volguus
Mar 3, 2009

User0015 posted:

That's where aws gets you. Their ec2 instances specifically lock down sqlite, so you run into a host of permission and access issues trying to get an app to open it. Smart for them, but it's really soured me obviously.

huh? I just tried it on two EC2 instances in aws (one running debian and the other centos). sqlite works normally.

Mr Shiny Pants
Nov 12, 2012

User0015 posted:

That's where aws gets you. Their ec2 instances specifically lock down sqlite, so you run into a host of permission and access issues trying to get an app to open it. Smart for them, but it's really soured me obviously.

You just have the file in your app directory, I wonder how they would lock that down.

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison

User0015 posted:

That's where aws gets you. Their ec2 instances specifically lock down sqlite, so you run into a host of permission and access issues trying to get an app to open it. Smart for them, but it's really soured me obviously.

uh what?

Adbot
ADBOT LOVES YOU

kitten emergency
Jan 13, 2008

get meow this wack-ass crystal prison
maybe look into lightstail or whatever the amazon cheap vps thing is too, i think it's slightly better specs than a micro ec2

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply